[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的情况,是无效的,调试源码也未能发现问题所在,只有两行都加的情况下才能有效,若有大神能观察到其中的问题所在,求教,本人将不胜感激。