我正在尝试选择 DataGrid 中的所有复选框,但使用下面的代码我没有得到任何结果
这是我在单击主 CheckBox 时调用的函数
private void CheckUnCheckAll(object sender, RoutedEventArgs e)
{
CheckBox chkSelectAll = ((CheckBox)sender);
if (chkSelectAll.IsChecked == true)
{
dgUsers.Items.OfType<CheckBox>().ToList().ForEach(x => x.IsChecked = true);
}
else
{
dgUsers.Items.OfType<CheckBox>().ToList().ForEach(x => x.IsChecked = false);
}
}
dgUsers 是 DataGrid,但我意识到找到了任何复选框。
这是我用来在数据网格中创建 CheckBox 的 XAML
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="col0" HeaderStyle="{StaticResource ColumnHeaderGripperStyle}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Click="CheckUnCheckAll" >
</CheckBox>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGrid.Columns>
这是我的DataGrid的图片
有没有办法以编程方式选择所有复选框?
编辑 我已经尝试关注 this steps
你可以看到我的代码在那里是一样的,但对我不起作用
最佳答案
TLDR;这就是你想要的,代码如下:
执行此操作的正确位置是在您的 ViewModel 中。您的 CheckBox 可以具有三种状态,所有这些您都想使用:
- 已检查 - 每一项都已检查
- 未选中 - 没有项目被选中
- 不确定 - 有些项目已检查,有些未检查
您将希望在选中/取消选中某个项目时更新 CheckBox,并在 CheckBox 更改时更新所有项目 - 仅以这种方式实现将使 CheckBox 处于无效状态,这可能会对用户体验产生负面影响。我的建议:一路走好,落实好。为此,您需要了解导致更改的原因 - 条目的 CheckBox 或标题中的 CheckBox。
下面是我的做法:
首先您需要为您的项目创建一个 ViewModel,我在这里使用了一个非常简化的模型,它只包含 IsChecked
属性。
public class Entry : INotifyPropertyChanged
{
private bool _isChecked;
public bool IsChecked
{
get => _isChecked;
set
{
if (value == _isChecked) return;
_isChecked = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
您的主 ViewModel 将包含所有项目的集合。每当项目的 IsChecked
属性发生变化时,您都必须检查是否选中/未选中所有 项目并更新 header 中的 CheckBox(或者更确切地说是其数据源的值) .
public class ViewModel : INotifyPropertyChanged
{
public List<Entry> Entries
{
get => _entries;
set
{
if (Equals(value, _entries)) return;
_entries = value;
OnPropertyChanged();
}
}
public ViewModel()
{
// Just some demo data
Entries = new List<Entry>
{
new Entry(),
new Entry(),
new Entry(),
new Entry()
};
// Make sure to listen to changes.
// If you add/remove items, don't forgat to add/remove the event handlers too
foreach (Entry entry in Entries)
{
entry.PropertyChanged += EntryOnPropertyChanged;
}
}
private void EntryOnPropertyChanged(object sender, PropertyChangedEventArgs args)
{
// Only re-check if the IsChecked property changed
if(args.PropertyName == nameof(Entry.IsChecked))
RecheckAllSelected();
}
private void AllSelectedChanged()
{
// Has this change been caused by some other change?
// return so we don't mess things up
if (_allSelectedChanging) return;
try
{
_allSelectedChanging = true;
// this can of course be simplified
if (AllSelected == true)
{
foreach (Entry kommune in Entries)
kommune.IsChecked = true;
}
else if (AllSelected == false)
{
foreach (Entry kommune in Entries)
kommune.IsChecked = false;
}
}
finally
{
_allSelectedChanging = false;
}
}
private void RecheckAllSelected()
{
// Has this change been caused by some other change?
// return so we don't mess things up
if (_allSelectedChanging) return;
try
{
_allSelectedChanging = true;
if (Entries.All(e => e.IsChecked))
AllSelected = true;
else if (Entries.All(e => !e.IsChecked))
AllSelected = false;
else
AllSelected = null;
}
finally
{
_allSelectedChanging = false;
}
}
public bool? AllSelected
{
get => _allSelected;
set
{
if (value == _allSelected) return;
_allSelected = value;
// Set all other CheckBoxes
AllSelectedChanged();
OnPropertyChanged();
}
}
private bool _allSelectedChanging;
private List<Entry> _entries;
private bool? _allSelected;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
演示 XAML:
<DataGrid ItemsSource="{Binding Entries}" AutoGenerateColumns="False" IsReadOnly="False" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:MainWindow}, Path=ViewModel.AllSelected}">Select All</CheckBox>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
</DataGrid.Columns>
</DataGrid>
关于c# - WPF 选择 DataGrid 中的所有 CheckBox,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48955781/