我有一个数据网格,显示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}
实现这一目标的最佳方法是什么?
答案 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)
由于对这篇文章缺乏回应以及我在这个问题上找不到资源,我选择了每一行中正常工作的按钮。