我已经搜索了很长一段时间,但我无法找到我的具体问题的答案。我有一个带有多个 DataGrid 的 WPF 应用程序,每个 DataGrid 包含 7 个自定义类型的对象,我将其称为
DataGridString
,其中包含属性 UnitType
和 Quantity
我希望能够使用拖放功能在 DataGrid 之间切换项目,这样当我将选定的项目从 DataGrid1 拖动到 DataGrid2 时,该项目就会插入到 DataGrid2 的鼠标放置位置,并且 DataGrid1 接收之前位于的项目DataGrid2 中新放置的项目。
我的应用程序看起来像这样:
我希望能够,比方说,选择第一个蓝色表格中的第 3 行(英雄 1:
UnitType
:Royal Griffin
,Quantity
:2
)并将项目放在第 4 行第二个,红色桌子(英雄2,UnitType
:(EMPTY)
,Quantity
:0
)。
到目前为止,我尝试的是按以下方式使用事件类型
MouseMove
、DragEnter
、Drop
:
XAML:
<DataGrid Name="DataGridUnitList1"
FontWeight="Regular"
FontSize="10"
CanUserSortColumns="False"
Grid.RowSpan="1"
Grid.Row="3"
Grid.Column="4"
Margin="3, 3, 3, 3"
Padding="0"
CanUserResizeColumns="False"
CanUserReorderColumns="False"
AreRowDetailsFrozen="True"
FrozenColumnCount="2"
IsReadOnly="True"
AutoGenerateColumns="False"
AllowDrop="True"
SelectionMode="Single"
MouseMove="DataGridUnitList_OnMouseMove"
DragEnter="DataGridUnitList_OnDragEnter"
Drop="DataGridUnitList_OnDrop"
CanUserAddRows="True"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Unit Type" Binding="{Binding UnitName}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
</DataGrid.Columns>
</DataGrid>
<DataGrid Name="DataGridUnitList2"
FontWeight="Regular"
FontSize="10"
CanUserSortColumns="False"
Grid.RowSpan="1"
Grid.Row="3"
Grid.Column="4"
Margin="3, 3, 3, 3"
Padding="0"
CanUserResizeColumns="False"
CanUserReorderColumns="False"
AreRowDetailsFrozen="True"
FrozenColumnCount="2"
IsReadOnly="True"
AutoGenerateColumns="False"
AllowDrop="True"
SelectionMode="Single"
MouseMove="DataGridUnitList_OnMouseMove"
DragEnter="DataGridUnitList_OnDragEnter"
Drop="DataGridUnitList_OnDrop"
CanUserAddRows="True"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Unit Type" Binding="{Binding UnitName}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
</DataGrid.Columns>
</DataGrid>
...
MainWindow.xaml.cs:
private void DataGridUnitList_OnMouseMove(object sender, MouseEventArgs e)
{
DataGrid dataGrid = sender as DataGrid;
if(e.LeftButton == MouseButtonState.Pressed)
{
DataGridString unit = (DataGridString)dataGrid.SelectedItem;
DataObject dragData = new DataObject("dragData", unit);
DragDrop.DoDragDrop(dataGrid, dragData, DragDropEffects.Move);
}
}
private void DataGridUnitList_OnDragEnter(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Move;
}
private void DataGridUnitList_OnDrop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("dragData"))
{
DataGridString unit = e.Data.GetData("dragData") as DataGridString;
DataGrid dataGrid = sender as DataGrid;
dataGrid.Items.Add(unit);
}
}
我知道显示的代码无法按预期工作,因为我当前仅添加新数据项,既不删除也不将任何新数据插入到另一个表中。我正在考虑当我用拖放放置项目时触发
DataGridUnitList_OnDrop
中的事件,以便我拖动项目的表格从“拖放表”发送项目。
这可能吗?我的失败方法还有其他选择吗?谢谢!
您可以通过从源集合中删除和添加项目来处理
PreviewMouseLeftButtonDown
容器的 Drop
和 DataGridRow
事件。这是一个可以帮助您顺利入门的示例:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataGridUnitList1.ItemsSource = new ObservableCollection<DataGridString> { ... };
DataGridUnitList2.ItemsSource = new ObservableCollection<DataGridString> { ... };
}
private void DataGridRow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
DataGridRow row = (DataGridRow)sender;
DataGridString unit = (DataGridString)row.DataContext;
DataObject dragData = new DataObject("dragData", unit);
DataGrid dataGrid = FindVisualParent<DataGrid>(row);
dragData.SetData("itemsSource", dataGrid.ItemsSource);
DragDrop.DoDragDrop(dataGrid, dragData, DragDropEffects.Move);
}
}
private void DataGridRow_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("dragData"))
{
DataGridString unitToAdd = e.Data.GetData("dragData") as DataGridString;
DataGridRow row = (DataGridRow)sender;
DataGrid dataGrid = FindVisualParent<DataGrid>(row);
ObservableCollection<DataGridString> targetCollection = dataGrid.ItemsSource as ObservableCollection<DataGridString>;
if (!targetCollection.Contains(unitToAdd))
{
DataGridString unitToRemove = row.DataContext as DataGridString;
ObservableCollection<DataGridString> sourceCollection = e.Data.GetData("itemsSource") as ObservableCollection<DataGridString>;
int index = targetCollection.IndexOf(unitToRemove);
if (index == -1)
index = 0;
sourceCollection.Remove(unitToAdd);
targetCollection.Insert(index, unitToAdd);
}
}
}
private static T FindVisualParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null)
return null;
var parentT = parent as T;
return parentT ?? FindVisualParent<T>(parent);
}
}
XAML:
<Window ...>
<Window.Resources>
<Style x:Key="DataGridRowStyle" TargetType="DataGridRow">
<Setter Property="AllowDrop" Value="True" />
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="DataGridRow_MouseLeftButtonDown" />
<EventSetter Event="Drop" Handler="DataGridRow_Drop" />
</Style>
</Window.Resources>
<StackPanel>
<DataGrid Name="DataGridUnitList1"
RowStyle="{StaticResource DataGridRowStyle}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Unit Type" Binding="{Binding UnitName}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
</DataGrid.Columns>
</DataGrid>
<DataGrid Name="DataGridUnitList2"
RowStyle="{StaticResource DataGridRowStyle}"
AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Unit Type" Binding="{Binding UnitName}" />
<DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}" />
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</Window>