C# WPF保持鼠标按钮通风孔向下
我有一个数据网格,在其中我使用DragAndDropBehavior向上/向下移动项目:C# WPF保持鼠标按钮通风孔向下,c#,wpf,xaml,C#,Wpf,Xaml,我有一个数据网格,在其中我使用DragAndDropBehavior向上/向下移动项目: public class DataGridRowDragAndDropBehavior { public delegate Point GetPosition(IInputElement element); int rowIndex = -1; public static DependencyProperty DataGridDr
public class DataGridRowDragAndDropBehavior
{
public delegate Point GetPosition(IInputElement element);
int rowIndex = -1;
public static DependencyProperty DataGridDragAndDropEnabled =
DependencyProperty.RegisterAttached("DataGridDragAndDropEnabled", typeof(bool),
typeof(DataGridRowDragAndDropBehavior), new UIPropertyMetadata(false, OnDataGridDragAndDropEnabled));
private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
{
var dataGrid = (DataGrid) sender;
dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
dataGrid.Drop +=Instance.productsDataGrid_Drop;
}
public static bool GetDataGridDragAndDropEnabled(DependencyObject obj)
{
return (bool) obj.GetValue(DataGridDragAndDropEnabled);
}
public static void SetDataGridDragAndDropEnabled(DependencyObject obj, bool value)
{
obj.SetValue(DataGridDragAndDropEnabled, value);
}
private static DataGridRowDragAndDropBehavior instance = new DataGridRowDragAndDropBehavior();
public static DataGridRowDragAndDropBehavior Instance
{
get { return instance; }
set { instance = value; }
}
void productsDataGrid_Drop(object sender, DragEventArgs e)
{
var dataGrid = (DataGrid) sender;
var dataGridSource = (System.Collections.IList)dataGrid.ItemsSource;
if (rowIndex < 0)
return;
var index = GetCurrentRowIndex(e.GetPosition,dataGrid);
if (index < 0)
return;
if (index == rowIndex)
return;
//if (index == dataGrid.Items.Count - 1)
//{
// MessageBox.Show("This row-index cannot be drop");
// return;
//}
var changedItem = dataGridSource[rowIndex];
dataGridSource.RemoveAt(rowIndex);
dataGridSource.Insert(index, changedItem);
}
void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var dataGrid = (DataGrid) sender;
rowIndex = GetCurrentRowIndex(e.GetPosition,dataGrid);
if (rowIndex < 0)
return;
dataGrid.SelectedIndex = rowIndex;
Register selectedEmp = dataGrid.Items[rowIndex] as Register;
if (selectedEmp == null)
return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
dataGrid.SelectedItem = selectedEmp;
}
}
private bool GetMouseTargetRow(Visual theTarget, GetPosition position)
{
Rect rect = VisualTreeHelper.GetDescendantBounds(theTarget);
Point point = position((IInputElement)theTarget);
return rect.Contains(point);
}
private DataGridRow GetRowItem(int index,DataGrid dataGrid)
{
if (dataGrid.ItemContainerGenerator.Status
!= GeneratorStatus.ContainersGenerated)
return null;
return dataGrid.ItemContainerGenerator.ContainerFromIndex(index)
as DataGridRow;
}
private int GetCurrentRowIndex(GetPosition pos,DataGrid dataGrid)
{
int curIndex = -1;
for (int i = 0; i < dataGrid.Items.Count; i++)
{
DataGridRow itm = GetRowItem(i,dataGrid);
if (GetMouseTargetRow(itm, pos))
{
curIndex = i;
break;
}
}
return curIndex;
}
}
一个更好的解决方案是使用
MouseMove
事件,并检查是否按下左键开始拖放:e.LeftButton==MouseButtonState.pressed
但是,如果您希望像在注释中建议的那样使用MouseDown
解决方案,那么您需要将事件冒泡并\或延迟DnD执行,因为这是进一步路由停止的原因
可能已经有了一些健壮的解决方案,但从我的头脑中,我们可以使用简单的计时器使其工作。为此,我们还需要PreviewMouseLeftButtonUp
:
private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
{
var dataGrid = (DataGrid)sender;
dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
dataGrid.PreviewMouseLeftButtonUp += Instance.productsDataGrid_PreviewMouseLeftButtonUp;
dataGrid.Drop += Instance.productsDataGrid_Drop;
}
然后我们只需要以延迟(这里是400毫秒)启动它,以便所有控件都有时间响应。当鼠标按钮打开时,我们停止:
private System.Timers.Timer dragTimer;
void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var dataGrid = (DataGrid)sender;
dragTimer = new System.Timers.Timer(400);
System.Timers.ElapsedEventHandler elapsed = null;
elapsed = (s, ee) =>
{
dragTimer.Elapsed -= elapsed;
dataGrid.Dispatcher.Invoke(() =>
{
rowIndex = GetCurrentRowIndex(e.GetPosition, dataGrid);
if (rowIndex < 0) return;
dataGrid.SelectedIndex = rowIndex;
object selectedEmp = dataGrid.Items[rowIndex];
if (selectedEmp == null) return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
dataGrid.SelectedItem = selectedEmp;
}
});
};
dragTimer.Elapsed += elapsed;
dragTimer.Start();
}
private void productsDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (dragTimer == null) return;
dragTimer.Stop();
dragTimer.Dispose();
dragTimer = null;
}
private System.Timers.Timer dragTimer;
void productsDataGrid\u PreviewMouseLeftButtonDown(对象发送器,鼠标按钮Ventargs e)
{
var dataGrid=(dataGrid)发送方;
dragTimer=新系统定时器定时器定时器(400);
System.Timers.ElapsedEventHandler EXPERSED=null;
经过=(s,ee)=>
{
dragTimer.appeated-=已用;
dataGrid.Dispatcher.Invoke(()=>
{
rowIndex=GetCurrentRowIndex(例如GetPosition,dataGrid);
if(rowIndex<0)返回;
dataGrid.SelectedIndex=rowIndex;
objectselectedemp=dataGrid.Items[rowIndex];
if(selectedEmp==null)返回;
DragDropEffects DragDropEffects=DragDropEffects.Move;
if(DragDrop.DoDragDrop(数据网格,selectedEmp,dragdropeffects)
!=DragDropEffects。无)
{
dataGrid.SelectedItem=selectedEmp;
}
});
};
dragTimer.appeated+=已用时间;
dragTimer.Start();
}
私有void productsDataGrid\u预览鼠标左键(对象发送器,鼠标按钮Ventargs e)
{
if(dragTimer==null)返回;
dragTimer.Stop();
dragTimer.Dispose();
dragTimer=null;
}
有很多方法可以让它变得更好,但它应该是这样工作的。这是一种奇怪的DnD方法,依赖MouseDown是混乱的。为什么不直接使用MouseMove并检查鼠标左键是否被按下(
e.LeftButton==MouseButtonState.pressed
)?你是对的。使用MouseMove事件也解决了我的问题:)。但是,如果我真的想使用MouseDown事件,您知道如何将其向下挖掘,以便它到达我的复选框吗?我不是说,您的答案是错误的,但这是一种“变通方法”。你知道如何让这件事成为泡泡吗?@KarolŻurowski,你不需要它来泡泡,你总是可以直接处理,而不依赖路由策略和谁来处理什么。
private static void OnDataGridDragAndDropEnabled(object sender, DependencyPropertyChangedEventArgs e)
{
var dataGrid = (DataGrid)sender;
dataGrid.PreviewMouseLeftButtonDown += Instance.productsDataGrid_PreviewMouseLeftButtonDown;
dataGrid.PreviewMouseLeftButtonUp += Instance.productsDataGrid_PreviewMouseLeftButtonUp;
dataGrid.Drop += Instance.productsDataGrid_Drop;
}
private System.Timers.Timer dragTimer;
void productsDataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var dataGrid = (DataGrid)sender;
dragTimer = new System.Timers.Timer(400);
System.Timers.ElapsedEventHandler elapsed = null;
elapsed = (s, ee) =>
{
dragTimer.Elapsed -= elapsed;
dataGrid.Dispatcher.Invoke(() =>
{
rowIndex = GetCurrentRowIndex(e.GetPosition, dataGrid);
if (rowIndex < 0) return;
dataGrid.SelectedIndex = rowIndex;
object selectedEmp = dataGrid.Items[rowIndex];
if (selectedEmp == null) return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(dataGrid, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
dataGrid.SelectedItem = selectedEmp;
}
});
};
dragTimer.Elapsed += elapsed;
dragTimer.Start();
}
private void productsDataGrid_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (dragTimer == null) return;
dragTimer.Stop();
dragTimer.Dispose();
dragTimer = null;
}