【问题标题】:IEnumerable in Model observable可观察模型中的 IEnumerable
【发布时间】:2018-06-28 12:44:51
【问题描述】:

我处于必须使用现有模型的情况下,我不允许更改现有属性。

public class Car : ModelBase
{
    private string _model;
    public string Model
    {
        get { return _model; }
        set { this.Update(x => x.Model, () => _model= value, _model, value); }
    }

    private IEnumerable<Person> _allowedDrivers;
    public IEnumerable<Person> AllowedDrivers
    {
        get { return _allowedDrivers; }
        set { this.Update(x => x.AllowedDrivers, () => _allowedDrivers=value, _allowedDrivers, value); }
    }
}

现在我们最近开始实现 WPF UI,我需要使用这些现有模型。有什么方法可以使用 IEnumerable 并让它像 ObservableCollection 一样工作而无需真正改变它?我有什么选择。

问题是我删除了一个 AllowedDriver,然后添加了一个 AllowedDriver,而 UI 根本没有更新。这是合乎逻辑的,然后我(出于测试目的)将 IEnumerable 设置为 ObservableCollection,然后 UI 工作。我是否有任何其他选项可以继续使用 IEnumerable 但已更新?

【问题讨论】:

  • IEnumerable 对计数、添加和删除一无所知。从理论上讲,它可能是一个无穷无尽的集合。也许你可以创建一个派生类?
  • public class Car () : Modelbase ... () ? Update(....) 是什么? ModelbaseSystem.Collections.Specialized.INotifyCollectionChangedSystem.ComponentModel.INotifyPropertyChanged 之类的吗?
  • “我是否有任何其他选项可以继续使用 IENumerable 但会得到更新?” -- 以“任何其他选项”形式出现的问题总是过于宽泛。当然当然你还有其他选择。但它们是否适用于你的情况,我们无从得知。无论如何,您采取的任何选择都不会像使用ObservableCollection&lt;T&gt; 那样有效。请注意,只要为AllowedDrivers 设置的对象实际上是ObservableCollection&lt;T&gt;,它就应该可以工作,即使属性类型IEnumerable&lt;T&gt;
  • @PeterDuniho:这是一个非常明确的问题,正如 Mihai Alexandru-lonut 发布的那样,答案非常明确。这种“所有没有答案的东西,比如 = 2 都必须关闭”形式的节制很糟糕,如果从一开始就这样做,那么就不一样了。
  • @Ignacio: "这是一个非常明确的问题,有一个非常明确的答案" -- 问题很明确,但没有a 明确的答案,它有很多。已经发布了两个完全不同的,并且不乏其他可能的。 “如果从一开始就是这样,那么 SO 就不一样了”——首先,SO 已经不“相同”。其次,有许多来自“早期”的问题在今天是不能容忍的,这是有充分理由的。这就是这些年来提问指南发生变化的原因和方式。

标签: c# wpf ienumerable observablecollection


【解决方案1】:

您可以简单地将 ObservableCollection分配到 AllowedDrivers 属性并对该集合进行操作:

var drivers = new ObservableCollection<Person>();
car.AllowedDrivers = drivers;

现在向drivers集合添加一个新的Person实际上会更新UI,因为绑定的UI元素会在运行时检查集合是否实现INotifyCollectionChanged

drivers.Add(new Person(...)); 

上面当然假设您的ModelBase.Update 方法没有做任何奇怪的事情,并最终将属性设置器的value 参数分配给其支持字段_allowedDrivers,以便属性获取器返回集合实例已传递给 setter。


编辑:如果可能的话,将 Car 类更改为使用 ICollection&lt;T&gt; 而不是 IEnumerable&lt;T&gt; 是有意义的:

public class Car : ModelBase
{
    ...

    private ICollection<Person> _allowedDrivers;
    public ICollection<Person> AllowedDrivers
    {
        get { return _allowedDrivers; }
        set { this.Update(x => x.AllowedDrivers, () => _allowedDrivers=value, _allowedDrivers, value); }
    }
}

您仍然可以分配一个 ObservableCollection,但去掉 drivers 变量:

car.AllowedDrivers = new ObservableCollection<Person>();
car.AllowedDrivers.Add(new Person(...)); 

【讨论】:

    【解决方案2】:

    感谢大家的意见。我通过将 IEnumerable 制作/转换为 ObservableCollection 来解决它。

    像这样:

      public class Car : ModelBase
      {
    
        public Car()
        {
            AllowedDrivers = new ObservableCollection<Person>();
        }
    
        private string _model;
        public string Model
        {
            get { return _model; }
            set { this.Update(x => x.Model, () => _model= value, _model, value); }
        }
    
        private IEnumerable<Person> _allowedDrivers;
        public IEnumerable<Person> AllowedDrivers
        {
            get { return _allowedDrivers; }
            set { this.Update(x => x.AllowedDrivers, () => _allowedDrivers=value, _allowedDrivers, value); }
        }
    }
    

    然后在我的视图模型中使用它,或者我这样使用它:

     var allowedDrivers = (ObservableCollection<Person>)Car.AllowedDrivers;
     allowedDrivers.Add(person)
    

    【讨论】:

    • 请注意,为了能够添加元素,只需转换为ICollection,如((ICollection&lt;Person&gt;)Car.AllowedDrivers).Add(person)。将视图模型更改为包含public ICollection&lt;Person&gt; AllowedDrivers { get; set; } 会很有意义。然后你可以简单地写Car.AllowedDrivers.Add(person)
    【解决方案3】:

    有什么方法可以使用 IEnumerable 并让它像 ObservableCollection 没有真正改变它?

    您可以创建另一个继承 Car 类的 。由于您的 ObservableCar 继承了 Car 类,因此您可以访问 AllowedDrivers 属性。

    因此,您可以声明您想要的observable 集合并使用从AllowedDrivers 转换而来的可观察集合进行初始化。这个初始化应该在get里面。

    public class ObservableCar: Car {
        public ObservableCar(){
             _observableAllowedDriver = new ObservableCollection<Person>(AllowedDrivers);
        }
        private ObservableCollection<Person> _observableAllowedDriver;
        public ObservableCollection<Person> ObservableAllowedDriver
        {
            get { return _observableAllowedDriver; }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 2013-02-12
      • 2012-09-02
      • 2011-01-07
      • 1970-01-01
      • 2014-12-24
      • 2013-11-14
      相关资源
      最近更新 更多