在WPF (c#)中拖放两个数据网格
本文关键字:数据 两个 数据网 网格 拖放 WPF | 更新日期: 2023-09-27 18:11:26
对不起,我的英语不是我的母语。如果有什么不明白的地方请告诉我。
我开始使用c#和WPF,我需要在两个数据网格之间实现拖放功能。我已经找了很多,但没有找到任何有用的东西。它总是显示如何在两个不同的控件之间进行拖放,或者仅在相同的数据网格中进行拖放,我无法根据我的需要调整这些答案,因为我不理解解决方案的某些部分。所以我来这里问一个非常精确的问题:如何实现两个数据网格之间的拖放?
如果你能帮助我,我将非常感激。
这是一个示例代码(更多细节在这里)
- 定义MouseDown事件
- 定义鼠标移动事件来启动拖放操作
- 定义拖放来测试是否允许拖放
- 定义Drop事件来执行Drop操作
您可以为两个数据网格使用相同的事件
private Point? _startPoint;
private void dataGrid_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_startPoint = e.GetPosition(null);
}
private void dataGrid_PreviewMouseMove(object sender, MouseEventArgs e)
{
// No drag operation
if (_startPoint == null)
return;
var dg = sender as DataGrid;
if (dg == null) return;
// Get the current mouse position
Point mousePos = e.GetPosition(null);
Vector diff = _startPoint.Value - mousePos;
// test for the minimum displacement to begin the drag
if (e.LeftButton == MouseButtonState.Pressed &&
(Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
{
// Get the dragged DataGridRow
var DataGridRow=
FindAnchestor<DataGridRow>((DependencyObject)e.OriginalSource);
if (DataGridRow == null)
return;
// Find the data behind the DataGridRow
var dataTodrop = (DataModel)dg.ItemContainerGenerator.
ItemFromContainer(DataGridRow);
if (dataTodrop == null) return;
// Initialize the drag & drop operation
var dataObj = new DataObject(dataTodrop);
dataObj.SetData("DragSource", sender);
DragDrop.DoDragDrop(dg, dataObj, DragDropEffects.Copy);
_startPoint = null;
}
}
private void dataGrid_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
_startPoint = null;
}
private void dataGrid_Drop(object sender, DragEventArgs e)
{
var dg = sender as DataGrid;
if (dg == null) return;
var dgSrc = e.Data.GetData("DragSource") as DataGrid;
var data = e.Data.GetData(typeof(DataModel));
if (dgSrc == null || data == null) return;
// Implement move data here, depends on your implementation
MoveDataFromSrcToDest(dgSrc, dg, data);
// OR
MoveDataFromSrcToDest(dgSrc.DataContext, dg.DataContext, data);
}
private void dataGrid_PreviewDragOver(object sender, DragEventArgs e)
{
// TO test if drop is allowed, to avoid drop
// if false e.Effects = DragDropEffects.None;
}
// Helper to search up the VisualTree
private static T FindAnchestor<T>(DependencyObject current)
where T : DependencyObject
{
do
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
希望有帮助
为此,您需要两个Datagrid提要列表或像xaml:
这样的observableCollection。<DataGrid AllowDrop="True" Name="dg1" Margin="10,50,10,30" Grid.Column="1">
//Set your column and what you want
</DataGrid>
<DataGrid Name="dg2" AllowDrop="True" Margin="10,50,10,30" Grid.Column="2">
//Set your column and what you want
</DataGrid>
我让你插入Datagrid的来源:
dg1.ItemSource = "yourlist1";
dg2.ItemSource = "yourlist2";
一旦源代码填入数据网格,将其添加到代码的顶部c#:
namespace YourAppName
{
public partial class MainWindow : Window
{
public delegate Point GetPosition(IInputElement element);
int rowIndex = -1;
string dgName;
public MainWindow()
{
dg1.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DgSupp_PreviewMouseLeftButtonDown);
dg1.Drop += new DragEventHandler(Dg_Drop);
dg2.PreviewMouseLeftButtonDown += new MouseButtonEventHandler(DgSupp_PreviewMouseLeftButtonDown);
dg2.Drop += new DragEventHandler(Dg_Drop);
}
然后将所有这些添加到MainWindow后面:
void Dg_Drop(object sender, DragEventArgs e)
{
int index = -1;
DataGrid dg = new DataGrid();
if (sender is DataGrid)
{
dg = (DataGrid)sender;
}
if (rowIndex < 0)
return;
if (dg.Name == "dg1")
{
index = this.GetCurrentRowIndexSupp(e.GetPosition);
}
if (dg.Name == "dg2")
{
index = this.GetCurrentRowIndexAdd(e.GetPosition);
}
if (index < 0)
return;
if (index == rowIndex)
return;
if (index == dg.Items.Count - 1)
{
MessageBox.Show("Last line can't moove");
return;
}
if (dg.Name == "dg1")
{
if (dgName == "dg2")
{
DataOfGrid changedProduct = yourlist2[rowIndex];
yourlist2.RemoveAt(rowIndex);
yourlist1.Insert(index, changedProduct);
}
else
{
DataOfGrid changedProduct = yourlist1[rowIndex];
yourlist1.RemoveAt(rowIndex);
yourlist1.Insert(index, changedProduct);
}
}
if (dg.Name == "dg2")
{
if (dgName == "dg1")
{
DataOfGrid changedProduct = yourlist1[rowIndex];
yourlist1.RemoveAt(rowIndex);
yourlist2.Insert(index, changedProduct);
}
else
{
DataOfGrid changedProduct = yourlist2[rowIndex];
yourlist2.RemoveAt(rowIndex);
yourlist2.Insert(index, changedProduct);
}
}
dg1.ItemsSource = yourlist1;
dg1.Items.Refresh();
dg2.ItemsSource = yourlist2;
dg2.Items.Refresh();
}
void DgSupp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DataGrid dg = new DataGrid();
if (sender is DataGrid)
{
dg = (DataGrid)sender;
}
if (dg.Name == "dg1")
{
rowIndex = GetCurrentRowIndexSupp(e.GetPosition);
dgName = dg.Name;
}
if (dg.Name == "dg2")
{
rowIndex = GetCurrentRowIndexAdd(e.GetPosition);
dgName = dg.Name;
}
if (rowIndex < 0)
return;
dg.SelectedIndex = rowIndex;
DataOfGrid selectedEmp = dg.Items[rowIndex] as DataOfGrid;
if (selectedEmp == null)
return;
DragDropEffects dragdropeffects = DragDropEffects.Move;
if (DragDrop.DoDragDrop(dg, selectedEmp, dragdropeffects)
!= DragDropEffects.None)
{
dg.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 GetRowItemList1(int index)
{
if (dg1.ItemContainerGenerator.Status
!= GeneratorStatus.ContainersGenerated)
return null;
return dg1.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
}
private DataGridRow GetRowItemList2(int index)
{
if (dg2.ItemContainerGenerator.Status
!= GeneratorStatus.ContainersGenerated)
return null;
return dg2.ItemContainerGenerator.ContainerFromIndex(index) as DataGridRow;
}
private int GetCurrentRowIndexSupp(GetPosition pos)
{
int curIndex = -1;
for (int i = 0; i < dg1.Items.Count; i++)
{
DataGridRow itm = GetRowItemList1(i);
if (GetMouseTargetRow(itm, pos))
{
curIndex = i;
break;
}
}
return curIndex;
}
private int GetCurrentRowIndexAdd(GetPosition pos)
{
int curIndex = -1;
for (int i = 0; i < dg2.Items.Count; i++)
{
DataGridRow itm = GetRowItemList2(i);
if (GetMouseTargetRow(itm, pos))
{
curIndex = i;
break;
}
}
return curIndex;
}
你所要做的就是把"dg1"answers"dg2"替换为你的Datagrid的名称,把"yourlist1"answers"yourlist2"替换为你的Datagrid的列表。
也请原谅我的英语,因为我根本不会说,我的灵感来自Raj Kumar的文章:https://www.c-sharpcorner.com/UploadFile/raj1979/drag-and-drop-datagrid-row-in-wpf/