【问题标题】:Howto observe converted collections?如何观察转换后的集合?
【发布时间】:2010-09-09 11:05:23
【问题描述】:

我将集合 ObservableCollection<Foo> 绑定到我的控制器上的依赖属性,但我通过 IValueConverter 运行它以使其改为 ObservableCollection<object>,这是我的控制器所期望的。转换工作正常 - 我创建了一个 ObservableCollection<object> 并用原始列表中的所有 Foo 填充它。然而,这带来了一个问题,即现在我正在观察值转换器中创建的集合,因此看不到对原始集合的任何更改。

所以;我是否必须在转换器中连接事件处理程序以手动保持转换后的集合与原始集合同步,还是有更好的方法来处理这个?我想如果不实际创建新集合就无法进行转换?或者我可以以某种巧妙的方式进行绑定,这样我就不必进行转换?

【问题讨论】:

    标签: .net wpf ivalueconverter


    【解决方案1】:

    我不知道它是否有帮助,但通常在 ViewModel 中,我将 IList 或另一个不太具体的接口声明为属性类型,而不是特定的接口。

    然后我可以将准所有集合和列表绑定到这个属性。

    在设置属性时,我检查它是否实现INotifyPropertyChanged,如果是,我附加一个 CollectionChanged-EventHandler。当属性发生新变化时,我从旧的 INotifyPropertyChanged 中删除 EventHandler(如果是的话)。

    这样做的缺点是,ViewModel 必须准备好查看与预期不同的类型的对象。但这通常是一项简单的工作。

    void YourDPValueChanged(DependencyPropertyChangedEventArgs e) {
        INotifyCollectionChanged newCollection = e.NewValue as INotifyCollectionChanged;
        INotifyCollectionChanged oldCollection = e.OldValue as INotifyCollectionChanged;
        if (null != newCollection) {
            newCollection.CollectionChanged += new NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
        }
        if (null != oldCollection) {
            oldCollection.CollectionChanged -= new NotifyCollectionChangedEventHandler(Collection_CollectionChanged);
        }
    

    【讨论】:

    • 感谢您的关注。我试过了,但它似乎对我没有帮助。我通常也使用 IList,但我认为问题在于列表包含的对象类型。我希望一个对象列表可以有一个绑定到它的任何东西的列表,但是只有当我将一个完全相同类型的集合绑定到它时才会触发依赖属性——在使用 IList 时也是如此..
    • @stiank81:这看起来是绑定的问题:ObservableCollection 实现了 Collection,而这实现了 IList。因此它不可能是包含类型的问题。我是否理解最初的设计正确:您的 ViewModel 具有此 IList 属性,并且您从 View 绑定 ObservableCollection 到它。对吗?
    • 我的 ViewModel 有一个 ObservableCollection,在我看来,我有一个带有属性 ObservableCollection 的控件,我将 ObservableCollection 绑定到该控件。由于类型不匹配,未应用绑定,似乎我必须更改其中一个才能在绑定中获得匹配。这就是我尝试使用 IValueConverter 解决的问题,但随后我得到了一个额外的集合,这意味着我失去了对 ViewModel 中原始 ObservableCollection 的跟踪。
    • @stiank81:好的,在这种情况下,如果您不想将 ViewModel 的属性更改为 IList 或 IEnumerable,我认为您必须编写一个转换器来进行转换并连接CollectionChanged 事件的源和目标集合。另一个想法可能是在 ViewModel 中添加第二个属性,该属性与特定的目的相同,但支持 IList?这使 VM 稍微复杂一点,但是您可以同时选择强类型和泛型。
    • 是的,看来这将是解决方案.. 考虑向我的 ViewModel 添加一个通用列表,但我不认为我愿意这样做.. 感谢您对此的意见!
    【解决方案2】:

    如果我理解正确,您正在通过创建新 ObservableCollection 的转换器绑定某种不实现 INotifyCollectionChanged 的​​ ICollection。在这种情况下,您不会从现在断开的集合中获得任何好处。 是否可以直接绑定您的集合(无需转换)并直接在您的对象上实现 INotifyPropertyChanged 和/或 INotifyCollectionChanged?

    【讨论】:

    • 如果问题不清楚,我很抱歉 - 代码的某些部分没有显示,但我现在添加了代码块。我将一个 ObservableCollection 绑定到一个 ObservableCollection 属性。问题是元素的类型,这就是为什么我必须添加一个转换器(或者有更好的方法吗?)。在转换器中创建了一个新集合,使我失去了对原始集合的观察。问题是如何最好地继续观察原始的。我可以添加更聪明的绑定吗?还是我需要手动让它们保持同步。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多