WPF拖放按钮
本文关键字:按钮 拖放 WPF | 更新日期: 2023-09-27 18:05:47
我正在编写一个具有按钮网格的WPF应用程序,我希望允许用户在网格之间拖放按钮,可能在应用程序的不同实例之间。我试过通过在按钮上添加一个处理程序到PreviewMouseMove事件,然后调用DoDragDrop,如果鼠标左键是下的,但是当我拖放按钮时,它总是以两次调用DoDragDrop和两次拖放事件处理程序结束。有人知道为什么会发生这种情况以及如何预防吗?
下面是一些演示问题的示例XAML:
<Window x:Class="WpfTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<Button PreviewMouseMove="PreviewMouseMove" x:Name="m_button" Width="250">
Hello, world!
</Button>
<Label Drop="Drop" AllowDrop="True">
Drop here!
</Label>
</DockPanel>
</Window>
和相应的代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void PreviewMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
++m_dragIndex;
System.Console.WriteLine("Dragged: " + m_dragIndex.ToString());
DragDrop.DoDragDrop(m_button, m_dragIndex, DragDropEffects.All);
e.Handled = true;
}
}
private void Drop(object sender, DragEventArgs e)
{
System.Console.WriteLine("Dropped: " + e.Data.GetData(typeof(Int32)).ToString());
}
private int m_dragIndex;
}
对于单个拖动,它被写入输出:
Dragged: 1
Dragged: 2
Dropped: 2
Dropped: 1
UPDATE:我已经更改了上面的示例代码,以显示当按钮被放置到某些东西上时调用哪些放置事件。
UPDATE:更新了问题,包括容器和应用程序实例之间的拖拽,因为这是使用拖拽系统的激励因素
我已经找到了一个解决办法-因为第一个DoDragDrop调用第二个PreviewMouseMove内部,我可以跟踪我是否已经在PreviewMouseMove调用和忽略它,如果我是。这看起来有点恶心,所以我希望有一个更好的解决方案。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void PreviewMouseMove(object sender, MouseEventArgs e)
{
if(!m_inMouseMove)
{
m_inMouseMove = true;
if (e.LeftButton == MouseButtonState.Pressed)
{
++m_dragIndex;
System.Console.WriteLine("Dragged: " + m_dragIndex.ToString());
DragDrop.DoDragDrop(m_button, m_dragIndex, DragDropEffects.All);
e.Handled = true;
}
m_inMouseMove = false;
}
}
private void Drop(object sender, DragEventArgs e)
{
System.Console.WriteLine("Dropped: " + e.Data.GetData(typeof(Int32)).ToString());
}
private int m_dragIndex;
bool m_inMouseMove;
}
我也遇到过同样的问题。我发现PreviewMouseMove调用两次,因为第一次它由容器元素(例如ListViewItem)和第二个-为TextBlock。所以我可以建议检查e.OriginalSource值的类型作为这个问题的另一个解决方案。