如何删除数据网格上的多个选定行

时间:2016-11-30 15:25:30

标签: c# mvvm datagrid

我有一个数据网格,显示SQL数据库表中存在的所有记录,我想在我的UI中添加一个按钮,允许用户删除他或她选择的记录。我为此找到的大多数引用都围绕向每行添加删除按钮或涉及代码。我正在使用MVVM模式,我不希望每行都有一个按钮。目前,我可以一次删除一条记录,但需要有关如何遍历所选项目的帮助。我的代码如下:

XAML

         <Button x:Name="revokeBtn"
                Grid.Row="0"
                Grid.Column="4"
                ToolTip="Revoke Selected License or Licenses"
                Content="Revoke"
                Command="{Binding RevokeSelectedCommand}"
                CommandParameter="{Binding}">
        </Button>

        <DataGrid x:Name="licenseGrid"
                  ItemsSource="{Binding LoggedUsers}"
                  SelectedItem="{Binding SelectedLicenses}"
                  Style="{DynamicResource DataGridStyle}"
                  Grid.Row="2"
                  Grid.Column="1"
                  Grid.ColumnSpan="6"
                  Height="535"
                  VerticalAlignment="Top"
                  IsReadOnly="True"
                  AutoGenerateColumns="False" 
                  HeadersVisibility="Column"
                  SelectionMode="Extended"
                  CanUserDeleteRows="True"
                  EnableRowVirtualization="False">
            <DataGrid.RowStyle>
                <Style TargetType="DataGridRow">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
                </Style>
            </DataGrid.RowStyle>

使用绑定到表列的DataGrid.Columns。

视图模型

    public ObservableCollection<MD_LoggedUsersModel> LoggedUsers
    {
        get { return _loggedUsers; }
        set { _loggedUsers = value; NotifyPropertyChanged(nameof(LoggedUsers)); }
    }

    public MD_LoggedUsersModel SelectedLicenses
    {
        get
        {
            return _selectedLicenses;
        }
        set
        {
            if (_selectedLicenses != value)
            {
                _selectedLicenses = value;
                OnPropertyChanged(nameof(SelectedLicenses));
            }
            if (_selectedLicenses == null)
            {
                LoadData();
            }
        }
    }

    public bool IsSelected
    {
        get
        {
            return _isSelected;
        }
        set
        {
            if (_isSelected == value) return;
            _isSelected = value;
            OnPropertyChanged(nameof(IsSelected));
        }
    }

    public ICommand RevokeSelectedCommand
    {
        get
        {
            return _revokeSelectedCommand ?? (_revokeSelectedCommand = new CommandHandler(() => RevokeSelected(), _canExecute));
        }
    }
    private void RevokeSelected()
    {need to iterate through selected rows here}

实现这一目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

几个月前我已经遇到过这个问题,因此我写了以下附属物:

 public class MultiSelectorExtensions
    {
        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.RegisterAttached(
            "SelectedItems",
            typeof(INotifyCollectionChanged),
            typeof(MultiSelectorExtensions),
            new PropertyMetadata(default(INotifyCollectionChanged), OnSelectedItemsChanged));

        private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MultiSelector multiSelectorControl = d as MultiSelector;

            NotifyCollectionChangedEventHandler handler = (sender, args) =>
            {
                if (multiSelectorControl != null)
                {
                    IList listSelectedItems = multiSelectorControl.SelectedItems;
                    if (args.OldItems != null)
                    {
                        foreach (var item in args.OldItems)
                        {
                            if (listSelectedItems.Contains(item))
                                listSelectedItems.Remove(item);
                        }
                    }

                    if (args.NewItems != null)
                    {
                        foreach (var item in args.NewItems)
                        {
                            if (!listSelectedItems.Contains(item))
                                listSelectedItems.Add(item);
                        }
                    }
                }
            };

            if (e.OldValue == null && multiSelectorControl != null)
            {
                multiSelectorControl.SelectionChanged += OnSelectionChanged;
            }

            if (e.OldValue is INotifyCollectionChanged)
            {
                (e.OldValue as INotifyCollectionChanged).CollectionChanged -= handler;
            }

            if (e.NewValue is INotifyCollectionChanged)
            {
                (e.NewValue as INotifyCollectionChanged).CollectionChanged += handler;
            }

        }

        private static void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            DependencyObject d = sender as DependencyObject;

            if (GetSelectionChangedInProgress(d))
                return;

            SetSelectionChangedInProgress(d, true);

            dynamic selectedItems = GetSelectedItems(d);

            try
            {
                foreach (dynamic item in e.RemovedItems.Cast<dynamic>().Where(item => selectedItems.Contains(item)))
                {
                    selectedItems.Remove(item);
                }
            }
            catch (Exception) { }

            try
            {
                foreach (dynamic item in e.AddedItems.Cast<dynamic>().Where(item => !selectedItems.Contains(item)))
                {
                    selectedItems.Add(item);
                }
            }
            catch (Exception){}

            SetSelectionChangedInProgress(d, false);
        }

        public static void SetSelectedItems(DependencyObject element, INotifyCollectionChanged value)
        {
            element.SetValue(SelectedItemsProperty, value);
        }

        public static INotifyCollectionChanged GetSelectedItems(DependencyObject element)
        {
            return (INotifyCollectionChanged)element.GetValue(SelectedItemsProperty);
        }

        private static readonly DependencyProperty SelectionChangedInProgressProperty = DependencyProperty.RegisterAttached(
            "SelectionChangedInProgress",
            typeof(bool),
            typeof(MultiSelectorExtensions),
            new PropertyMetadata(default(bool)));

        private static void SetSelectionChangedInProgress(DependencyObject element, bool value)
        {
            element.SetValue(SelectionChangedInProgressProperty, value);
        }

        private static bool GetSelectionChangedInProgress(DependencyObject element)
        {
            return (bool)element.GetValue(SelectionChangedInProgressProperty);
        }
    }

在视图中的DataGrid处,您必须使用此附加属性,例如:

<DataGrid x:Name="licenseGrid"
          ItemsSource="{Binding LoggedUsers}"
          SelectedItem="{Binding SelectedLicenses}"
          Style="{DynamicResource DataGridStyle}"
          Grid.Row="2"
          Grid.Column="1"
          Grid.ColumnSpan="6"
          Height="535"
          VerticalAlignment="Top"
          IsReadOnly="True"
          AutoGenerateColumns="False" 
          HeadersVisibility="Column"
          SelectionMode="Extended"
          CanUserDeleteRows="True"
          EnableRowVirtualization="False"
          MyAttachedProperties:MultiSelectorExtensions.SelectedItems="{Binding SelectedLoggedUsers, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></DataGrid>

MyAttachedProperties是MultiSelectorExtension类所在的命名空间。

然后在你的viewmodel中你有一个看起来像这样的属性:

private ObservableCollection<MD_LoggedUsersModel> selectedLoggedUsers;
public ObservableCollection<MD_LoggedUsersModel> SelectedLoggedUsers
{
    get { return selectedLoggedUsers; }
    set 
    { 
        selectedLoggedUsers = value;
        NotifyPropertyChanged(nameof(SelectedLoggedUsers)); 
    }
}

重要提示:在viewmodel的构造函数中,您必须使用

初始化SelectedLoggedUsers
SelectedLoggedUsers = new ObservableCollection<MD_LoggedUsersModel>();

否则该属性将为null,并且附加属性将不起作用。

答案 1 :(得分:0)

由于对这篇文章缺乏回应以及我在这个问题上找不到资源,我选择了每一行中正常工作的按钮。