我正在尝试创建一个在拖动可拖动项目时跟随鼠标指针的弹出窗口。

以下剪接会在鼠标指针处打开弹出窗口,但我依靠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;
    }
}


弹出窗口本身位于我的窗口的主网格中。

注意

我曾尝试在MouseMovePreviewMouseMove期间处理位置,但是在拖放过程中这些事件将被完全忽略。

<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);
        }

10-06 15:16