我有一个看起来像这样的 DataGrid:
<DataGrid Name="Users" ItemsSource="{Binding Users, Mode=TwoWay}"
AutoGenerateColumns="False" Grid.ColumnSpan="2" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox Name="SelectAllUsers"
Checked="SelectAllUsers_Checked"
Unchecked="SelectAllUsers_Unchecked"/>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox x:Name="SelectUser"
IsChecked="{Binding IsSelected, Mode=TwoWay}"
Checked="SelectUser_Checked"
Unchecked="SelectUser_Unchecked"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="UserName"
Binding="{Binding UserName}"
Header="Name" IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
它目前数据绑定(bind)到
BindingList
在 View 模型中:class SecurityDialogViewModel
{
public BindingList<User> Users { get; set; }
User
是具有 INotifyPropertyChanged
的 DTO实现(Fody.PropertyChanged):[AddINotifyPropertyChangedInterface]
class User
{
public int UserId { get; set; }
public string UserName { get; set; }
public bool IsSelected { get; set; }
}
SelectAllUsers_Checked
在 ViewModel 中有一些代码将所有复选框设置为 true,然后调用 ViewModel 中的方法以根据用户 BindingList 集合中的复选框选择执行一些魔术(现在全部选中):private void SelectAllUsers_Checked(object sender, RoutedEventArgs e)
{
SelectAll(Users, true);
(DataContext as MyViewModel).PerformMagic();
}
private void SelectAll(DataGrid dataGrid, bool value)
{
foreach (dynamic d in dataGrid.ItemsSource)
{
d.IsSelected = value;
}
}
这一切都很好。但是,检查单个用户不会。底层绑定(bind)列表显然保持不变:
private void SelectUser_Checked(object sender, RoutedEventArgs e)
{
(DataContext as MyViewModel).PerformMagic(); // Doesn't execute
}
我以为我知道为什么。
BindingList
不会触发 PropertyChanged
事件,直到你离开记录。但是取消选中另一行上的另一个复选框(从而移出原始记录并据称触发 PropertyChanged
事件)也没有效果。我真正需要的是一个集合,它会在单击 DataGrid 行复选框之一时触发 PropertyChanged 事件。
我该怎么做呢?我可以将
ObservableCollection
子类化吗?并捕捉其中一个事件?还是我需要自己写?也许我可以简单地将一个事件 Hook 到现有的 ObservableCollection
目前没有被观察到?
最佳答案
好吧,结果证明解决方案比我想象的要简单得多:
private void SelectUser_Checked(object sender, RoutedEventArgs e)
{
var binding = (sender as CheckBox).GetBindingExpression(CheckBox.IsCheckedProperty);
binding.UpdateSource(); // Triggers PropertyChanged Notification
(DataContext as MyViewModel).PerformMagic();
}
这也有效:
<CheckBox
x:Name="SelectUser"
IsChecked="{Binding IsSelected, UpdateSourceTrigger=PropertyChanged}" />
注意事项
BindableList
有自己的问题。DataGrid
对其应用排序,这意味着您必须 subclass it if you want this capability . BindingList
未实现 INotifyCollectionChanged
如果绑定(bind)到控件的 ItemsSource
将导致内存泄漏属性(property)。 最终我决定使用
ObservableCollection
并在代码隐藏中进行事件处理,而不是尝试依赖数据绑定(bind)事件。结果证明它更简单,更容易掌握,不需要任何特殊的集合子类,并且我得到了我想要的精细控制水平。进一步阅读
The UpdateSourceTrigger property
Sortable BindingList Implementation
Another Sortable BindingList Implementation
关于c# - 单击 DataGrid 行中的复选框时触发 PropertyChanged 事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49017596/