【问题标题】:How can I add a calculated additional column in WPF DataGrid / ListView / ListBox如何在 WPF DataGrid / ListView / ListBox 中添加计算的附加列
【发布时间】:2012-11-29 10:42:39
【问题描述】:

我有一个DataGrid 和一个视图模型 (MyViewModel1)。 DataGrid 绑定到 MyViewModel1 的 Items 属性。约束是我不能碰MyViewModel1MyClass1的代码。

public class MyViewModel1 : INotifyPropertyChanged
{
    ...
    public ObservableCollection<MyClass1> Items { get { ... } }
    public int ViewModelProperty1 { get { ... } }
    public int ViewModelProperty2 { get { ... } }
}

public class MyClass1 : INotifyPropertyChanged
{
    ...
    public int Property1 { get { ... } }
    public int Property2 { get { ... } }
    public int Property3 { get { ... } }
}

我希望 DataGrid 不仅显示具有 3 个已知属性的 3 列,而且还显示每行的第 4 列,这取决于 Property1Property2Property3ViewModelProperty1ViewModelProperty2。举例来说,假设第 4 列是Property1 + Property2 + Property3 + ViewModelProperty1 + ViewModelProperty2。第 4 列必须显示当前值,因此如果 ViewModelProperty1 增加 1,则第 4 列也必须增加 1。我的问题是:我有什么选择来做到这一点?

我能想到这些:

  1. 使用 IMultiValueConverter 并将所有因变量作为输入。这适用于示例。这里的问题是,一旦变量的相互作用变得更加复杂,例如((Property1 + 2*Property2) * Property3) ^ (ViewModelProperty1 - ViewModelProperty2),将 5 个变量放入“MultiBinding”的顺序变得很重要,并且在绑定中有很多知识会导致解决方案变得脆弱。

  2. 使用包装器。将DataGrid 绑定到一个新类MyViewModel2,它注册到MyViewModel1 上的更改,看起来像

    public class MyViewModel2
    {
        public MyViewModel2(MyViewModel1 m) { ... }
        ...
        public ObservableCollection<MyClass2> Items { get { ... } }
    }
    public class MyClass2 : INotifyPropertyChanged
    {
        public MyClass2(MyClass1 inner)
        {
            InnerClass = inner;
            InnerClass.NotifyPropertyChanged += InnerClassChanged;
        }
        void InnerClassChanged(object o, PropertyChangedEventArgs)
        {
            if (PropertyChanged != null)
                PropertyChanged("Property4");
        }
        public void ViewModelPropertiesChanged
        {
            if (PropertyChanged != null)
                PropertyChanged("Property4");
        }
    
        public MyClass1 InnerClass { get; private set; }
        public int Property4
        {
            get { return InnerClass.Property1+InnerClass.Property2 ... }
        }
        public event PropertyChanged;
    }
    

问题是除了我上面提到的两个(转换器和包装器)之外,还有什么方法可以解决这个问题。

我的问题不是哪种方法是解决示例的最佳方法。

【问题讨论】:

  • 确实没有其他干净的方法(例如:您可以将组合数据字段放在代码隐藏中)。但是,值得注意的是,您的多值转换器可以调用另一个对象来执行值转换。这可以通过将潜在的业务逻辑带回某个共享类来使其不那么“脆弱”。

标签: c# .net wpf data-binding


【解决方案1】:

对不起,我刚刚看到你已经想到了这个!我并不理解你的反对意见。

您可以使用MultiBindingIMultiValueConverter。请参阅 IMultiValueConverter 文档中的示例。

(来自这里:https://stackoverflow.com/a/2002598/360211

【讨论】:

  • 感谢您的回复。为了提供更多背景信息,我过去曾多次遇到过这个问题,在我处理的实际案例中,有时会更多,有时会少于此示例所具有的 5 个依赖项。在一种情况下,我有 15 个因变量分布在 3 个类中,因此“MultiBinding”方法变得不切实际。这一点到底在哪里是主观的。对于有 2-3 个变量的情况,我经常使用“MultiBinding”。如果有一些类似于扩展方法的方式,或者带有附加属性的东西,那就太好了。
  • 听起来您的视图模型离视图太远了。视图模型应该代表视图中显示的数据。在xaml 中可以使用一些简单的格式和简单的算术运算,但是包含 15 个变量的复杂计算告诉我,视图模型中缺少一些主要内容。为什么不能触摸视图模型本身?
  • 在为相似的“视图”共享相同的“视图模型”与为每个“视图”使用一个“视图模型”之间取得平衡。我发现有些项目的每个“视图”有一个“视图模型”在维护上过于繁重,通常最好在多个视图之间共享一个设计良好的视图模型,使用简单的“IValueConverter”和“IMultiValueConverter”类弥补差异。 15 个变量的情况确实导致了额外的“ViewModel”(Wrapper),但我正在寻找其他解决方案,其中“MultiBinding”和额外的“ViewModel”都不完美。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-12
  • 2023-02-08
  • 2018-06-06
  • 2021-11-14
  • 2019-03-26
  • 1970-01-01
  • 2013-06-09
相关资源
最近更新 更多