C# WPF GridView具有多个复选框列,并选择所有列标题

C# WPF GridView具有多个复选框列,并选择所有列标题,c#,wpf,listview,checkbox,C#,Wpf,Listview,Checkbox,我有一个包含几个GridViewColumns的ListView。有几列是复选框。每个列标题也包含一个复选框,用于选中/取消选中该列中的所有复选框。每行的复选框都绑定到“我的视图模型”中的属性。我看到过一些帖子,其中场景是一列复选框,但这些解决方案都不适合我,因为我有4列复选框。我还需要保持从一次访问到下一次访问的选择状态(可以选中列中的所有、部分或无复选框) 以下是我的ListView的XAML的缩写版本: 我尝试过使用命令和命令参数,在Checked属性上使用PropertyChange

我有一个包含几个GridViewColumns的ListView。有几列是复选框。每个列标题也包含一个复选框,用于选中/取消选中该列中的所有复选框。每行的复选框都绑定到“我的视图模型”中的属性。我看到过一些帖子,其中场景是一列复选框,但这些解决方案都不适合我,因为我有4列复选框。我还需要保持从一次访问到下一次访问的选择状态(可以选中列中的所有、部分或无复选框)

以下是我的ListView的XAML的缩写版本:


我尝试过使用命令和命令参数,在Checked属性上使用PropertyChanged事件,并在代码中处理Checked事件,但是没有任何信息可以让我知道在绑定到的集合中要更改什么

我想我可以为每一个创建一个单独的事件处理程序,但如果可能的话,我希望能够在单个事件处理程序中处理这个问题,因为最终我将创建一个自定义控件,该控件在显示的列方面更易于使用


提前感谢

只需提供所需的信息,并通过反射完成剩余的工作,例如



如果您想坚持使用MVVM方法,我建议使用绑定方法而不是事件处理方法,因为MVVM避免在代码隐藏文件中编写代码


一种方法是在视图模型中简单地绑定两个bool属性,并选中两个复选框的
IsChecked
属性。基于使用InotifyPropertyChanged的更改通知,您可以迭代您的itemssource,即AveragingParameters,并更改
CalMin
CalAverage

我已使用一个命令和一个标记解决了我的问题,该标记包含我要设置的模型属性的名称,以及一个CommandParameter设置为绑定到标记的多重绑定,并选中复选框财产。守则如下:

我的视图的Xaml资源:

<UserControl.Resources>
   <converters:NameValueMultiBindingConverter x:Key="SelectAllConverter" />
</UserControl.Resources>
我在转换器中使用的结果对象:

public class NameValueConverterResult
{
    //The name of the model property to set
    public string Name { get; set; }

    //The value we're setting it to
    public object Value { get; set; }
}
DelegateCommand(我正在使用PRISM)和视图模型中的处理程序

public ICommand SelectAllCheckedCommand { get; private set; }
private void OnSelectAllCheckedCommand(object arg )
{
   if (arg == null || !(arg is NameValueConverterResult)) return;

   NameValueConverterResult prop = arg as NameValueConverterResult;

   //Reflect on the model to find the property we want to update.
   PropertyInfo propInfo = Averagers.FirstOrDefault().GetType().GetProperty(prop.Name);
   if (propInfo == null) return;

   //Set the property on the Model
   foreach (var item in Averagers)
      propInfo.SetValue(item, prop.Value, null);
} 

我希望我没有滥用StackOverflow提供了我提出的解决方案。我不确定这里的礼节。

你想知道当用户选中或取消选中
chkAvgSelectAll
chkMinSelectAll
时,你需要在
AveragingParameters
中做些什么更改吗?我正在尝试找出如何链接到我的视图模型,并确定我需要对视图中的每个项目执行哪些布尔属性我的AveragingParameters集合。H.B.下面的帖子可能就是问题所在。我不确定我是否理解这个问题。如果将每列绑定到ModelView中的单个属性/字段,则当该复选框状态更改时,基础绑定对象也会更改。不需要确定哪个布尔属性,它是通过绑定显式的。也许我不明白这个问题。@SRM,也许我遗漏了什么,但是我的模型的状态被持久化了,我需要在以后的访问中保留网格中每个项目的布尔值(很抱歉在我的原始帖子中没有提及)。看来你的解决方案会打破这个问题。这就是为什么我不能使用触发器。仅供参考,我确实使用多重绑定解决了我的问题,解决方案将很快发布。谢谢您的帖子。我试试看。我假设DPData与我在原始帖子中调用的平均参数一致。只是任何类型的项目来源,是的。你的帖子给了我一些想法。因为我使用的是MVVM,所以我的最终解决方案使用了多重绑定。我将很快发布我的解决方案。这是对MVVM的常见误解。MVVM不要求任何代码隐藏。它所规定的是代码背后没有业务逻辑。我听人这样说:“代码隐藏应该是设计师的专属领域”。换句话说,如果您有代码隐藏,请确保它是特定于视图的,并且没有业务逻辑。否则,您的视图模型中会出现视图逻辑的糟糕组合,就像在视图中放置业务逻辑一样糟糕。顺便说一句,谢谢您的帖子。我实际上使用mult绑定解决了这个问题。我很快就会把它作为一个解决方案。我相信@SRM对于MVVM和codebehind是正确的。如果您需要对WPF和Silverlight的支持,遵循这些指导原则将使您能够轻松地支持其他视图。至于您提出的解决方案,我希望尽可能避免绑定到多个属性。原因是,这段代码的下一次迭代很可能是一个用户控件,它允许动态设置列数。今天我有4列复选框。未来的使用者可能需要不同的视图模型,并且需要更多或更少的列。
public class NameValueMultiBindingConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter,
                          System.Globalization.CultureInfo culture)
    {

        var parameters = (object[])values;
        return new NameValueConverterResult 
                        { 
                           Name = (string)parameters[0], 
                           Value = parameters[1] 
                        };
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, 
                                System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
public class NameValueConverterResult
{
    //The name of the model property to set
    public string Name { get; set; }

    //The value we're setting it to
    public object Value { get; set; }
}
public ICommand SelectAllCheckedCommand { get; private set; }
private void OnSelectAllCheckedCommand(object arg )
{
   if (arg == null || !(arg is NameValueConverterResult)) return;

   NameValueConverterResult prop = arg as NameValueConverterResult;

   //Reflect on the model to find the property we want to update.
   PropertyInfo propInfo = Averagers.FirstOrDefault().GetType().GetProperty(prop.Name);
   if (propInfo == null) return;

   //Set the property on the Model
   foreach (var item in Averagers)
      propInfo.SetValue(item, prop.Value, null);
}