通过拖放在 DataGrid 之间交换项目

问题描述 投票:0回答:1

我已经搜索了很长一段时间,但我无法找到我的具体问题的答案。我有一个带有多个 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
中的事件,以便我拖动项目的表格从“拖放表”发送项目。

这可能吗?我的失败方法还有其他选择吗?谢谢!

c# wpf xaml event-handling
1个回答
0
投票

您可以通过从源集合中删除和添加项目来处理

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>
© www.soinside.com 2019 - 2024. All rights reserved.