我正在研究wpf(mvvm架构)。我正在使用数据网格列出复选框,并在标题中单击“全选”复选框,我希望选中所有复选框,反之亦然。请帮忙。
我在这里给出我的代码描述...... 这是View.xaml
<DataGridCheckBoxColumn Binding="{Binding IsSelected}" Width="50" >
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate x:Name="dtAllChkBx">
<CheckBox Name="cbxAll" Content="All" IsChecked="{Binding Path=DataContext.AllSelected,RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTemplateColumn Header="Name" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding UsecaseName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
下面是viewmodel类
private bool _IsSelected;
public bool IsSelected
{
get { return _IsSelected; }
set
{
_IsSelected = value;
OnPropertyChanged("IsSelected");
}
}
private bool _AllSelected;
public bool AllSelected
{
get { return _AllSelected; }
set
{
_AllSelected = value;
foreach (var reportListItemModel in UsecaseListItems)
{
reportListItemModel.IsSelected = this._AllSelected;
}
OnPropertyChanged("IsSelected");
}
}
private ObservableCollection<UseCase> _usecaseListItems = new ObservableCollection<UseCase>();
public ObservableCollection<UseCase> UsecaseListItems
{
get { return _usecaseListItems; }
set {
_usecaseListItems = value;
OnPropertyChanged("UsecaseListItems");
}
}
公共类用例:BaseNotifyPropertyChanged { 公共字符串 UsecaseName { get;放; }
public bool IsSelected { get; set; }
}
还应该做什么才能使全选复选框正常工作?
您的 UseCase 类必须实现 INotifyPropertyChanged 接口
public class UseCase : INotifyPropertyChanged
{
//...
private bool _isSelected;
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
_isSelected = value;
NotifyPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
编辑:这里我得到了一个运行良好的完整示例
*.xaml(视图)
<DataGrid x:Name="dataGrid" ItemsSource="{Binding MyCollection}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsSelected}" Width="50" >
<DataGridCheckBoxColumn.HeaderTemplate>
<DataTemplate x:Name="dtAllChkBx">
<CheckBox Name="cbxAll" DataContext="{Binding ElementName=dataGrid, Path=DataContext}" Command="{Binding MyCommand}" CommandParameter="{Binding Path=IsChecked, RelativeSource={RelativeSource Self}}"/>
</DataTemplate>
</DataGridCheckBoxColumn.HeaderTemplate>
</DataGridCheckBoxColumn>
<DataGridTemplateColumn Header="Name" Width="SizeToCells" IsReadOnly="True">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding UsecaseName}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
*.cs(视图模型)
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
for (int i = 0; i < 100; i++)
{
MyCollection.Add(new UseCase { UsecaseName = "name " + i, IsSelected = false });
}
MyCommand = new RelayCommand(MyCommandAction);
}
private ObservableCollection<UseCase> myCollection = new ObservableCollection<UseCase>();
public ObservableCollection<UseCase> MyCollection
{
get
{
return myCollection;
}
set
{
myCollection = value;
NotifyPropertyChanged("MyCollection");
}
}
public RelayCommand MyCommand { get; set; }
private void MyCommandAction(object obj)
{
foreach (var item in MyCollection)
{
item.IsSelected = (bool)obj;
}
}
//NotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
*.cs(模型)
public class UseCase : INotifyPropertyChanged
{
public string UsecaseName { get; set; }
private bool _isSelected;
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
_isSelected = value;
NotifyPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
虽然存在很多解决方案,但我想找到一个我经常遇到的特定问题陈述,类似于: 在 WPF DataGrid 中,通过 MVVM 方法绑定,
型号:
public class Employee : INotifyPropertyChanged
{
private int _id;
private string _name;
private double _salary;
private bool _isSelected;
public int Id { get => _id; set => _id = value; }
public string Name { get => _name; set => _name = value; }
public double Salary { get => _salary; set => _salary = value; }
public bool IsSelected
{
get
{
return _isSelected;
}
set
{
_isSelected = value;
OnPropertyChanged(nameof(IsSelected));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyname)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
}
}
}
视图模型:
public class EmployeeDetailsViewModel
{
public EmployeeDetailsViewModel()
{
SelectAllCommand = new DelegateCommand<bool?>(HandleSelectAllCommand);
}
ObservableCollection<Employee> _employees = null;
/// <summary>
/// Collection bound to DataGrid
/// </summary>
public ObservableCollection<Employee> Employees { get => _employees; set { _employees = value; } }
/// <summary>
/// Command bound to SelectAll checkbox in XAML
/// </summary>
public ICommand SelectAllCommand { get; set; }
private void HandleSelectAllCommand(bool? isChecked)
{
if (isChecked.HasValue)
{
foreach (var employee in Employees)
{
employee.IsSelected = isChecked.Value;
}
}
}
void PrepareData()
{
this.Employees = new ObservableCollection<Employee>()
{
new Employee{Id=1, Name="abc", Salary=100000.00d},
new Employee{Id=2, Name="def", Salary=200000.00d},
new Employee{Id=3, Name="ghi", Salary=300000.00d},
new Employee{Id=4, Name="jkl", Salary=400000.00d}
};
}
}
视图(XAML):
<DataGrid ItemsSource="{Binding Employees}" AutoGenerateColumns="False" CanUserAddRows="False" >
<DataGrid.Columns>
<DataGridTemplateColumn >
<DataGridTemplateColumn.Header>
<CheckBox x:Name="chkSelectAll">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path = DataContext.SelectAllCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid,AncestorLevel=1}}"
CommandParameter="{Binding ElementName=chkSelectAll, Path=IsChecked, UpdateSourceTrigger=PropertyChanged}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Unchecked">
<local:EventTriggerPropertySetAction TargetObject="{Binding ElementName=chkSelectAll}" PropertyName="IsChecked" PropertyValue="False"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn Binding="{Binding Id}" Header="Id"/>
<DataGridTextColumn Binding="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Header="Name"/>
<DataGridTextColumn Binding="{Binding Salary, UpdateSourceTrigger=PropertyChanged}" Header="Salary"/>
</DataGrid.Columns>
</DataGrid>
要访问交互触发器,您需要将以下名称空间添加到 Window/UserControl 标记中:
<Window x:Class="TestApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
....
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
简化的重要部分是由于
<local:SetPropertyAction ...
基于这个SO答案或这个SO答案。
当您访问这些链接时,不要忘记投票和鼓励;)
希望这对某人有所帮助!
您可以使用 RegisteredAttachedProperty 使其成为可能。 在这里,您可以找到样本。你可以从那里得到启发。
您可能需要这个解决方案:
https://stackoverflow.com/a/77603913/6859121
易于使用!
<DataGrid.Columns>
<!-- Binding to bool property for entity which means it checked -->
<fc:DataGridCheckAllColumn Binding="{Binding IsChecked}" />
<!-- else columns -->
<DataGridTextColumn Binding="{Binding EntityName}" />
</DataGrid.Columns>