C# 如何在WPF DataGrid中按DataGrid标题复选框选择列的所有复选框
我有一个带有一个CheckBoxColumn的DataGrid。在该复选框列的标题中,我添加了一个复选框以选中该Datagrid行的所有复选框 我怎样才能做到这一点 WPF dataGrid的我的XAML代码:C# 如何在WPF DataGrid中按DataGrid标题复选框选择列的所有复选框,c#,wpf,wpfdatagrid,C#,Wpf,Wpfdatagrid,我有一个带有一个CheckBoxColumn的DataGrid。在该复选框列的标题中,我添加了一个复选框以选中该Datagrid行的所有复选框 我怎样才能做到这一点 WPF dataGrid的我的XAML代码: <DataGrid AutoGenerateColumns="False" CanUserAddRows="False" Grid.RowSpan="2" Height="130" HorizontalAlignment="Left" IsReadOnly="False"
<DataGrid AutoGenerateColumns="False" CanUserAddRows="False" Grid.RowSpan="2" Height="130" HorizontalAlignment="Left" IsReadOnly="False" Margin="189,340,0,0" Name="dgCandidate" TabIndex="7" VerticalAlignment="Top" Width="466" Grid.Row="1" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="colCandidateID" Binding="{Binding CandidateID}" Header="SlNo" MinWidth="20" IsReadOnly="True" />
<DataGridTextColumn x:Name="colRegistraion" Binding="{Binding RegisterNo}" Header="Reg. No." IsReadOnly="True" />
<DataGridTextColumn x:Name="colCandidate" Binding="{Binding CandidateName}" Header="Name" MinWidth="250" IsReadOnly="True" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox Name="chkSelectAll" Checked="chkSelectAll_Checked" Unchecked="chkSelectAll_Unchecked"></CheckBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate >
<DataTemplate >
<CheckBox x:Name="colchkSelect1" Checked="colchkSelect1_Checked" Unchecked="colchkSelect1_Unchecked" ></CheckBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
我添加了复选框以选中Datagrid行中的所有复选框
如果您的意思是在datagrid列中选中所有复选框,那么我会说:只需使用checked/unchecked更新itemssource集合
public bool SelectAll
{
get{return this._selectAll;}
set
{
this._selectAll = value;
this.MyItemsSourceCollection.ForEach(x=>x.MyRowCheckProperty=value);
this.OnPropertyChanged("SelectAll");
}
}
xaml
我不知道xaml绑定是否正确,但我希望您能看到我的意图将候选类转换为如下内容:
public class Candidate : DependencyObject
{
//CandidateID Dependency Property
public int CandidateID
{
get { return (int)GetValue(CandidateIDProperty); }
set { SetValue(CandidateIDProperty, value); }
}
public static readonly DependencyProperty CandidateIDProperty =
DependencyProperty.Register("CandidateID", typeof(int), typeof(Candidate), new UIPropertyMetadata(0));
//RegisterNo Dependency Property
public int RegisterNo
{
get { return (int)GetValue(RegisterNoProperty); }
set { SetValue(RegisterNoProperty, value); }
}
public static readonly DependencyProperty RegisterNoProperty =
DependencyProperty.Register("RegisterNo", typeof(int), typeof(Candidate), new UIPropertyMetadata(0));
//CandidateName Dependency Property
public string CandidateName
{
get { return (string)GetValue(CandidateNameProperty); }
set { SetValue(CandidateNameProperty, value); }
}
public static readonly DependencyProperty CandidateNameProperty =
DependencyProperty.Register("CandidateName", typeof(string), typeof(Candidate), new UIPropertyMetadata(""));
//BooleanFlag Dependency Property
public bool BooleanFlag
{
get { return (bool)GetValue(BooleanFlagProperty); }
set { SetValue(BooleanFlagProperty, value); }
}
public static readonly DependencyProperty BooleanFlagProperty =
DependencyProperty.Register("BooleanFlag", typeof(bool), typeof(Candidate), new UIPropertyMetadata(false));
}
在MainWindow.xaml中:
<DataGrid ItemsSource="{Binding CandidateList}">
<DataGrid.Columns>
<DataGridTextColumn Header="Id" Binding="{Binding CandidateID}"/>
<DataGridTextColumn Header="RegNr" Binding="{Binding RegisterNo}"/>
<DataGridTextColumn Header="Name" Binding="{Binding CandidateName}"/>
<DataGridTemplateColumn>
<DataGridTemplateColumn.Header>
<CheckBox Checked="CheckBox_Checked" Unchecked="CheckBox_Checked"></CheckBox>
</DataGridTemplateColumn.Header>
<DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<CheckBox IsChecked="{Binding BooleanFlag}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
在MainWindow.xaml.cs中:
public MainWindow()
{
DataContext = this;
CandidateList.Add(new Candidate()
{
CandidateID = 1,
CandidateName = "Jack",
RegisterNo = 123,
BooleanFlag = true
});
CandidateList.Add(new Candidate()
{
CandidateID = 2,
CandidateName = "Jim",
RegisterNo = 234,
BooleanFlag = false
});
InitializeComponent();
}
//List Observable Collection
private ObservableCollection<Candidate> _candidateList = new ObservableCollection<Candidate>();
public ObservableCollection<Candidate> CandidateList { get { return _candidateList; } }
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
foreach (var item in CandidateList)
{
item.BooleanFlag = true;
}
}
private void UnheckBox_Checked(object sender, RoutedEventArgs e)
{
foreach (var item in CandidateList)
{
item.BooleanFlag = false;
}
}
public主窗口()
{
DataContext=this;
候选名单。添加(新候选人()
{
CandidateID=1,
CandidateName=“杰克”,
寄存器no=123,
布尔标志=真
});
候选名单。添加(新候选人()
{
CandidateID=2,
CandidateName=“吉姆”,
寄存器no=234,
BooleanFlag=false
});
初始化组件();
}
//列表可观察集合
私有ObservableCollection_candidateList=新ObservableCollection();
公共可观察集合候选列表{get{return{u候选列表;}}
已选中私有无效复选框(对象发送方、路由目标方)
{
foreach(候选名单中的var项目)
{
item.BooleanFlag=true;
}
}
已选中私有无效取消复选框(对象发送方,路由目标e)
{
foreach(候选名单中的var项目)
{
item.BooleanFlag=false;
}
}
严格来说,模型不应该知道视图,因此blindmeis提出的解决方案打破了MVVM/表示设计模式,模型更改正在更新数据网格中的每一行。请记住,在MVVM中,依赖关系流是View->ViewModel->Model,因此,如果您在视图模型(或控件代码隐藏)中引用控件,那么您已经有效地打破了该模式,并且可能会在以后的过程中遇到问题 事实证明,这比人们希望的要困难得多
第一个问题是,不能只将视图模型绑定到列标题,因为它没有视图模型作为其数据上下文,因此需要绑定代理将绑定正确路由到视图模型
public class BindingProxy : Freezable
{
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
"Data",
typeof(object),
typeof(BindingProxy),
new UIPropertyMetadata(null));
public object Data
{
get { return this.GetValue(DataProperty); }
set { this.SetValue(DataProperty, value); }
}
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
}
现在在数据网格的资源中创建绑定代理:
<DataGrid.Resources>
<aon:BindingProxy
x:Key="DataContextProxy"
Data="{Binding}" />
</DataGrid.Resources>
而SelectAllCommand
属性是ICommand
的一个实现,其中Execute
方法是:
public void Execute(object parameter)
{
var allSelected = this.AreAllSelected;
switch (allSelected)
{
case true:
this.AreAllSelected = false;
break;
case false:
case null:
this.AreAllSelected = true;
break;
}
}
最后,行项目视图模型(即
项目
中的内容)需要在每次选择的值
更改时在主视图模型上提升属性更改
。如何做到这一点完全取决于您。这应该是DataGrid的来源。(如果定义为ObservaleCollection更好)MyBooleanProperty也应该是DependencyProperty,它在从DependencyObject继承的MyItemType中定义。如果太混乱,请让我发布更详细的回答谢谢你。。事实上,我是新手,所以这些有点让我困惑,所以请进一步解释…为了使绑定工作,需要将数据类型定义为DependencyObjects,将属性定义为DependencyProperty。尽量避免使用x:Name,而是使用绑定。如果必须为xaml元素提供列表,请不要通过编写循环来填充元素的“Items”,而是使用ItemsSource=“{Binding someList}”。someList应该是一个可观察的集合。someType应该从DependencyObject继承。最后,您需要为xaml设置DataContext,我更喜欢在*.xaml.cs文件中设置它。如上所述(在构造函数中)。注意:为了定义依赖属性,请使用propdp代码段。(写propdp,按Tab键两次,然后填写突出显示的区域。)非常感谢您的工作,我正在用SQL表在我的项目上实现它……它的显示错误不包含MyItemsSourceCollection的定义这是一个示例,您必须使用属性名称
<DataGridTemplateColumn>
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate>
<CheckBox
Command="{Binding
Data.SelectAllCommand,
Source={StaticResource DataContextProxy}}"
IsChecked="{Binding
Data.AreAllSelected,
Mode=OneWay,
Source={StaticResource DataContextProxy},
UpdateSourceTrigger=PropertyChanged}"
IsThreeState="True" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox
IsChecked="{Binding
Path=IsSelected,
UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
public bool? AreAllSelected
{
get
{
return this.Items.All(candidate => candidate.IsSelected)
? true
: this.Items.All(candidate => !candidate.IsSelected)
? (bool?)false
: null;
}
set
{
if (value != null)
{
foreach (var item in this.Items)
{
item.IsSelected = value.Value;
}
}
this.RaisePropertyChanged();
}
}
public void Execute(object parameter)
{
var allSelected = this.AreAllSelected;
switch (allSelected)
{
case true:
this.AreAllSelected = false;
break;
case false:
case null:
this.AreAllSelected = true;
break;
}
}