[QS] 同一个UI多个拥有右键菜单功能及数据拖动功能的Datagrid出现的假死问题

场景
多个DataGrid,每个Datagrid拥有右键菜单功能及数据拖动功能,会出现界面假死情况,如下图所示,第三步骤点击DataGrid one时将不会有任何反应,使用snoop查看事件发现,第二步操作后,DataGrid Two就没有释放鼠标捕捉
操作步骤
为了方便,直接上图,共三个步骤,如下所示:


相关后台代码:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            var ls = new List<string> {"ss1", "ss2", "ss3"};
            dg1.ItemsSource = ls;
            var ls1 = new List<string> { "ss1", "ss2"};
            dg2.ItemsSource = ls1;

            dg1.ContextMenu=new ContextMenu();
            dg1.ContextMenu.Items.Add("con1");
            dg1.ContextMenu.Items.Add("con1");
            dg1.ContextMenu.Items.Add("con1");

            dg1.MouseMove += dg1_MouseMove;
            dg2.MouseMove += dg2_MouseMove;
        }


        void dg2_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && dg2.IsKeyboardFocusWithin)
            {
                var item = dg2.GetMouseTargetItem(e.GetPosition) as DataGridRow;

                if (null != item && item.IsSelected)
                {
                    DragDrop.DoDragDrop(dg2, dg2.SelectedItem, DragDropEffects.Move);
                    //dg2.CaptureMouse();
                    //dg2.ReleaseMouseCapture();
                    e.Handled = true;
                }
            }
        }

        void dg1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed && dg1.IsKeyboardFocusWithin)
            {
                var item = dg1.GetMouseTargetItem(e.GetPosition) as DataGridRow;

                if (null != item && item.IsSelected)
                {
                    DragDrop.DoDragDrop(dg1, dg1.SelectedItem, DragDropEffects.Move);
                    e.Handled = true;
                }
            }
        }

    }

    public static class SelectorExtend
    {
        public delegate Point GetPosition(IInputElement element);

        private static DependencyObject GetItemByIndex(this Selector selector, int index)
        {
            if (null == selector)
                return null;
            if (selector.ItemContainerGenerator.Status
                != GeneratorStatus.ContainersGenerated)
                return null;
            return selector.ItemContainerGenerator.ContainerFromIndex(index);
        }

        private static bool IsMouseTargetItem(Visual theTarget, GetPosition pos)
        {
            if (null == theTarget)
                return false;
            Rect rect = VisualTreeHelper.GetDescendantBounds(theTarget);
            Point point = pos((IInputElement)theTarget);
            return rect.Contains(point);
        }

        public static object GetMouseTargetItem(this Selector selector, GetPosition pos)
        {
            if (null == selector)
                return null;
            for (int i = 0; i < selector.Items.Count; i++)
            {
                var itm = selector.GetItemByIndex(i);
                if (IsMouseTargetItem(itm as Visual, pos))
                {
                    return itm;
                }
            }
            return null;
        }
    }

解决方案
即为代码中注释的两行代码,具体为什么,实话说,我也不是很清楚,该问题困扰了好几天,作过各种代码尝试,如,只有release的情况,是无效的,调试源码也未能发现问题所在,只有两行都加的情况下才能有效,若有大神能观察到其中的问题所在,求教,本人将不胜感激。

原文地址:https://www.cnblogs.com/maigc249/p/5528511.html