如何通过单击删除SelectedItem?

时间:2018-03-31 20:06:32

标签: c# wpf xaml datagrid

假设我在DataGrid上选择了一个项目,我可以使用UnselectAll删除所有选定项目,但我想知道如何通过再次点击它来删除所选项目。

示例

  1. 用户选择item1
  2. 选择已更改事件正在触发
  3. 用户再次点击Item1并删除选择
  4. 我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:0)

我所知道的没有内置功能。您需要在后面的代码中处理此功能,方法是订阅PreviewMouseDown上的DataGrid事件。还有其他方法可以解决这个问题(即附加行为,自定义控制等),但这种方式可能是最直接的。一旦你明白了,你就可以开发自己的实现了。

这是一个如何实现这一目标的简单示例。看起来有点长,但这是一个完整的工作示例。请提取您需要的部件。

基本理念是:

  1. 订阅数据网格上的PreviewMouseDown事件。
  2. 当事件触发时,您需要找到点击的项目。
  3. 要查找单击的项目,请使用e.OriginalSource属性,然后使用提供的帮助方法FindParentOfType向上走可视树以查找DataGridRow。
  4. 获得该行后,其DataContext就是单击的项目。
  5. 点击项目后,检查它是否存在于DataGrid的SelectedItems属性中。如果是这样,请将其删除。
  6. 如果找到并删除了项目,请务必使用e.Handled = true,以便数据网格在同一次点击时不会选中该项目。如果没有删除该项,请不要执行任何操作,只需让DataGrid选择它即可。
  7. <强>的Xaml:

    <Window x:Class="WpfApp.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <!--The items source is binding to whatever the datacontext is, 
                    which is the Window DataContext set in the code behind-->
            <DataGrid x:Name="myDataGrid" ItemsSource="{Binding}" 
                      PreviewMouseDown="DataGrid_PreviewMouseDown"/>
        </Grid>
    </Window>
    

    代码背后:

    using System.Collections.ObjectModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace WpfApp
    {
        public class TestData
        {
            public string Prop1 { get; set; }
            public string Prop2 { get; set; }
            public string Prop3 { get; set; }
        }
    
        public partial class MainWindow : Window
        {
            ObservableCollection<TestData> Data = new ObservableCollection<TestData>();
    
            public MainWindow()
            {
                //Get some data
                Data.Add(new TestData { Prop1 = "Column11", Prop2 = "Column12", Prop3 = "Column13" });
                Data.Add(new TestData { Prop1 = "Column21", Prop2 = "Column22", Prop3 = "Column23" });
                Data.Add(new TestData { Prop1 = "Column31", Prop2 = "Column32", Prop3 = "Column33" });
                Data.Add(new TestData { Prop1 = "Column41", Prop2 = "Column42", Prop3 = "Column43" });
                InitializeComponent();
                //assign our collection to the Window DataContext
                DataContext = Data;
            }
            //this is where all the magic happens
            private void DataGrid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
            {
                DataGrid dataGrid = sender as DataGrid;
                DataGridRow row = findParentOfType<DataGridRow>(e.OriginalSource as DependencyObject);
                if(dataGrid != null && row != null)
                {
                    //the row DataContext is the selected item
                    if(dataGrid.SelectedItems.Contains(row.DataContext))
                    {
                        dataGrid.SelectedItems.Remove(row.DataContext);
                        //mark event as handled so that datagrid does not      
                        //just select it again on the current click.
                        e.Handled = true;
                    }
                }
            }
    
            //This helper is used to find your target, which in your case is a DataGridRow.
            //In general, if you continue with WPF, I would suggest adding
            //this very handy method to your extensions library.
            private T findParentOfType<T>(DependencyObject source) where T : DependencyObject
            {
                T ret = default(T);
                UIElement parent = VisualTreeHelper.GetParent(source) as UIElement;
    
                if (parent != null)
                {
                    ret = parent as T ?? findParentOfType<T>(parent) as T;
                }
                return ret;
            }
        }
    }