Mar*_*ons 8 c# wpf xaml datagrid
我正在尝试在DataGrid中选择所有CheckBox,但我没有使用此代码获得任何结果
这是我在单击主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);
}
}
Run Code Online (Sandbox Code Playgroud)
dgUsers是DataGrid,但我发现任何复选框都找到了.
这是我正在使用的XAML在数据网格中创建CheckBox
<DataGrid.Columns>
<DataGridCheckBoxColumn x:Name="col0" HeaderStyle="{StaticResource ColumnHeaderGripperStyle}">
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate>
<CheckBox Click="CheckUnCheckAll" >
</CheckBox>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGrid.Columns>
Run Code Online (Sandbox Code Playgroud)
这是我的DataGrid的图片
有没有办法以编程方式选择所有复选框?
编辑 我已经尝试按照这个步骤
你可以看到我的代码是相同的,但对我不起作用
Man*_*mer 19
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));
}
}
Run Code Online (Sandbox Code Playgroud)
您的主ViewModel将包含所有项目的集合.每当项目的IsChecked属性发生变化时,您都必须检查是否已选中/取消选中所有项目,并更新标题中的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));
}
}
Run Code Online (Sandbox Code Playgroud)
演示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>
Run Code Online (Sandbox Code Playgroud)
这是基于@Manfred解决方案的修改。我用Command而不是event.
XAML:
<DataGrid ItemsSource="{Binding Students}" AutoGenerateColumns="True" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding DataContext.IsAllSelected, RelativeSource={RelativeSource AncestorType=DataGrid}}" Command="{Binding DataContext.CheckAllStudentsCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" Command="{Binding DataContext.CheckStudentCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
视图模型:
public class MainWindowViewModel : INotifyPropertyChanged
{
private List<Student> students;
public List<Student> Students
{
get { return students; }
set { students = value; OnPropertyChanged(); }
}
private bool? isAllSelected;
public bool? IsAllSelected
{
get { return isAllSelected; }
set { isAllSelected = value; OnPropertyChanged(); }
}
public RelayCommand CheckStudentCommand { get; private set; }
public RelayCommand CheckAllStudentsCommand { get; private set; }
public MainWindowViewModel()
{
Students = new List<Student>() { new Student { Name = "Walter" }, new Student { Name = "Jenny" }, new Student { Name = "Joe" } };
CheckStudentCommand = new RelayCommand(OnCheckStudent);
CheckAllStudentsCommand = new RelayCommand(OnCheckAllStudents);
IsAllSelected = false;
}
private void OnCheckAllStudents()
{
if (IsAllSelected == true)
Students.ForEach(x => x.IsChecked = true);
else
Students.ForEach(x => x.IsChecked = false);
}
private void OnCheckStudent()
{
if (Students.All(x => x.IsChecked))
IsAllSelected = true;
else if (Students.All(x => !x.IsChecked))
IsAllSelected = false;
else
IsAllSelected = null;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Run Code Online (Sandbox Code Playgroud)
源代码可以在这里找到