我正在尝试创建一个在拖动可拖动项目时跟随鼠标指针的弹出窗口。
以下剪接会在鼠标指针处打开弹出窗口,但我依靠GiveFeedback
委托来允许我更新弹出位置(即,如果指针已移动)
private void Members_DragOver(object sender, DragEventArgs e)
{
dragPopup.DataContext = DraggedItem;
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
dragPopup.IsOpen = true;
}
private void Members_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (dragPopup.IsOpen)
{
var mousePoint = Mouse.GetPosition(this);
dragPopup.HorizontalOffset = mousePoint.X + this.Left + 10;
dragPopup.VerticalOffset = mousePoint.Y + this.Top + 10;
dragPopup.IsOpen = true;
}
}
弹出窗口本身位于我的窗口的主网格中。
注意
我曾尝试在
MouseMove
或PreviewMouseMove
期间处理位置,但是在拖放过程中这些事件将被完全忽略。<Popup x:Name="dragPopup" Placement="MousePoint">
<Border BorderThickness="2" Background="White" DataContext="{Binding}">
<StackPanel Orientation="Horizontal" Margin="4,3,8,3">
<TextBlock Text="{Binding FullName}" FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
</Border>
</Popup>
GiveFeedback
代表仅触发一次(将断点计数设置为5的断点可以确认这一点)。即使this MSDN article说:在拖放操作期间,将连续引发此事件。因此,您应该避免事件处理程序中的资源密集型任务。例如,每次引发GiveFeedback事件时,请使用缓存的游标而不是创建新的游标。
为什么代表只被解雇一次?
最佳答案
没错,GiveFeedBack是做到这一点的方法,我确实设法在拖动过程中调用了GiveFeedBack。显然,在GiveFeedBack中的鼠标位置的处理方式与鼠标移动不同。我设法通过使用WinForms鼠标位置来解决此问题。为以下代码添加参考System.Windows.Forms和System.Drawing:
Xaml:
<Grid GiveFeedback="Members_GiveFeedback">
<Popup x:Name="dragPopup" Placement="MousePoint">
<Border BorderThickness="2" Background="White" DataContext="{Binding}">
<StackPanel Orientation="Horizontal" Margin="4,3,8,3">
<TextBlock Text="Test" FontWeight="Bold" VerticalAlignment="Center" Margin="8,0,0,0" />
</StackPanel>
</Border>
</Popup>
<StackPanel Orientation="Horizontal">
<ListBox x:Name="sourcList" Height="50"
PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown"
PreviewMouseMove="sourcList_PreviewMouseMove"
AllowDrop="True" >
<ListBoxItem > source Item #1</ListBoxItem>
</ListBox>
<ListBox x:Name="droplist" Height="50" AllowDrop="True" Drop="droplist_Drop" >
<ListBoxItem >dest Item #2</ListBoxItem>
</ListBox>
</StackPanel>
</Grid>
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var mousePoint = Mouse.GetPosition(this);
startPoint=mousePoint;
var point = GetMousePositionWindowsForms();
var formsmousePoint = new Point(point.X, point.Y);
var pointfromscreen = dragPopup.PointFromScreen(formsmousePoint);
dragPopup.HorizontalOffset = pointfromscreen.X - 100;
dragPopup.VerticalOffset = pointfromscreen.Y - 100;
dragPopup.IsOpen = true;
}
private void sourcList_PreviewMouseMove(object sender, MouseEventArgs e)
{
...
}
private void droplist_Drop(object sender, DragEventArgs e)
{
...
}
private void Members_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
if (dragPopup.IsOpen)
{
var point=GetMousePositionWindowsForms();
var mousePoint = new Point(point.X, point.Y);
var pointfromscreen=dragPopup.PointFromScreen(mousePoint);
dragPopup.HorizontalOffset = pointfromscreen.X-100;
dragPopup.VerticalOffset = pointfromscreen.Y-100;
}
}
public static Point GetMousePositionWindowsForms()
{
System.Drawing.Point point = System.Windows.Forms.Control.MousePosition;
return new Point(point.X, point.Y);
}