我希望这是一个很好的问题,所以我会详细地写下我想实现的目标,我在互联网上发现的东西,并展示我迄今为止所做的以及我所做的努力。
我需要在应用程序中添加拖放功能。我有图像(基本上是控件),我想将其拖到列表框的项目中。
以下是示例UI:
下面是我现在的用法:
正如您所看到的,我可以拖动四个图像中的一个,并将其放到列表框项目上。
若我将图像移动到正确的目标(列表框图像)上,光标附近的图像就会消失,一切都正常,但当我不将图像放在列表项上时(我松开鼠标),图像会留在屏幕上。
我的解决方案基于
this
问题,我无法删除不需要的窗口(光标附近的图像)
我的XAML如下所示:
<Window x:Class="DragDrop.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Drag'n'Drop" Height="350" Width="525"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<ListBox HorizontalAlignment="Right" HorizontalContentAlignment="Stretch" Height="300" Margin="0,10,10,0" VerticalAlignment="Top" Width="234" ItemsSource="{Binding People}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" AllowDrop="True" PreviewDrop="UIElement_OnPreviewDrop">
<TextBlock Text="{Binding Name}" FontWeight="Bold" />
<ProgressBar Height="20" Value="{Binding Points}" Margin="0,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Image HorizontalAlignment="Left" Height="72" Margin="10,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-60000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="10"/>
<Image HorizontalAlignment="Left" Height="72" Margin="87,10,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="20"/>
<Image HorizontalAlignment="Left" Height="72" Margin="10,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-7000-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="30"/>
<Image HorizontalAlignment="Left" Height="72" Margin="87,87,0,0" VerticalAlignment="Top" Width="72" Source="Images/coins-700-icon.png" RenderTransformOrigin="0.5,0.5"
PreviewMouseLeftButtonDown="OnMouseTouchDown"
PreviewTouchDown="OnMouseTouchDown"
PreviewGiveFeedback="UIElement_OnPreviewGiveFeedback" Tag="40"/>
</Grid>
</Window>
以及后面的代码:
public partial class MainWindow
{
private readonly ObservableCollection<Person> _people = new ObservableCollection<Person>();
public ObservableCollection<Person> People
{
get { return _people; }
}
public MainWindow()
{
InitializeComponent();
_people.Add(new Person() {Name = "Person1", Points = 10});
_people.Add(new Person() {Name = "Person2", Points = 0});
_people.Add(new Person() {Name = "Person3", Points = 40});
}
private void OnMouseTouchDown(object sender, InputEventArgs e)
{
var item = sender as Image;
if (item == null) return;
var draggedItem = item;
var points = Convert.ToInt32(draggedItem.Tag);
CreateDragDropWindow(draggedItem);
System.Windows.DragDrop.DoDragDrop(draggedItem, points, DragDropEffects.Move);
}
private Window _dragdropWindow;
private void CreateDragDropWindow(Visual dragElement)
{
_dragdropWindow = new Window
{
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
AllowDrop = false,
Background = null,
IsHitTestVisible = false,
SizeToContent = SizeToContent.WidthAndHeight,
Topmost = true,
ShowInTaskbar = false
};
Rectangle r = new Rectangle
{
Width = ((FrameworkElement) dragElement).ActualWidth/2,
Height = ((FrameworkElement) dragElement).ActualHeight/2,
Fill = new VisualBrush(dragElement)
};
_dragdropWindow.Content = r;
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
_dragdropWindow.Left = w32Mouse.X;
_dragdropWindow.Top = w32Mouse.Y;
_dragdropWindow.Show();
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
private void UIElement_OnPreviewGiveFeedback(object sender, GiveFeedbackEventArgs e)
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
_dragdropWindow.Left = w32Mouse.X;
_dragdropWindow.Top = w32Mouse.Y;
}
private void UIElement_OnPreviewDrop(object sender, DragEventArgs e)
{
var droppedData = (Int32) e.Data.GetData(typeof (Int32));
var stackPanel = sender as StackPanel;
if (stackPanel != null)
{
var student = stackPanel.DataContext as Person;
if (student != null) student.Points += droppedData;
}
if (_dragdropWindow != null)
{
_dragdropWindow.Close();
_dragdropWindow = null;
}
}
}
public class Person : INotifyPropertyChanged
{
private string _name;
private int _points;
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
OnPropertyChanged();
}
}
public int Points
{
get { return _points; }
set
{
if (value == _points) return;
_points = value;
if (_points >= 100)
{
_points -= 100;
Debug.WriteLine("100!");
}
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
我在互联网上发现,我可以使用扩展Adorner的类,我找到了一些示例:
但所有这些都显示了如何从集合(ItemsControls)中拖动项。第三个环节很有希望,但我没能适应我的需求。
所以我的问题是:
-
当我取消拖动(鼠标向上或不正确的拖动目标)时,如何隐藏示例中的小图像窗口
-
演示我使用Adorner,以及如何在代码中使用它?当我正确放置图像或取消拖放目标不正确时,我需要在开始拖放和隐藏时显示它
我是从WPF开始的,所以请试着理解我的沮丧——我已经花了最后两个晚上和晚上的时间试图让这个工作。