【问题标题】:Implementing INotifyCollectionChanged on custom list在自定义列表上实现 INotifyCollectionChanged
【发布时间】:2018-12-31 10:54:22
【问题描述】:

我目前在 UWP 中有一个类,它是一堆不同类型列表的包装器,包括我构建的自定义列表。此包装器需要绑定到某种列表,例如 ListView、ListBox、GridView 等。

问题是当我尝试实现INotifyCollectionChanged 时,UI 元素似乎没有将处理程序附加到CollectionChangedPropertyChanged 处理程序(处理程序总是null)。但是,将列表从我的自定义列表更改为 ObservableCollection 似乎工作正常。为了让 UI 将其集合更改为我的类,我缺少什么?

我当前的实现看起来像

public class MyWrapperList<T> : IList<T>, INotifyPropertyChanged, INotifyCollectionChanged
{
    private IEnumerable<T> _source;

    // Implement all interfaces here, including my custom GetEnumerator() and all my add, insert, remove, etc classes
}

请注意,我不想像许多其他答案所暗示的那样从 ObservableCollection 继承,因为我希望这是一个查看原始列表的包装器。

编辑:您可以在 GitHub 上找到可重现的问题示例:https://github.com/nolanblew/SampleCollectionChanged/

【问题讨论】:

  • 它可能会帮助您查看 ObservableCollection 的源代码,看看它是如何工作的 - github.com/Microsoft/referencesource/blob/master/System/compmod/… - 除了拥有正确的事件并在正确的位置触发它之外,没有什么神奇之处但是时间。
  • 谢谢。我看了看,我不明白为什么我的收藏更改事件没有被附加到。我正在尝试通过按钮更新集合,因此 UI 列表已经加载并且所有绑定都已解决。但是当我得到触发事件的代码时,事件处理程序总是null
  • 当您在 XAML ItemsControl 上设置 ItemsSource 时,它​​会自动尝试将其转换为 INotifyCollectionChanged 并连接事件,因此除非您的实际事件声明有错误,否则没有您没有明显的原因发布一个小的可调示例项目。
  • 当然。您可以在 GitHub 上找到示例:github.com/nolanblew/SampleCollectionChanged 这应该只是源代码的包装器。我在 NDA 中删除了我的自定义代码,但这应该足够了,因为问题仍然存在

标签: c# xaml binding uwp


【解决方案1】:

为了让 ListView 自动绑定到您的集合,您必须实现 both INotifyCollectionChange IList(注意:这是 非泛型 IList)。

如果您修改示例代码以使您的自定义列表类实现IList

public class MyWrapperList<T> : IList<T>, INotifyPropertyChanged, INotifyCollectionChanged, IList
{

    //... all your existing code plus: (add your own implementation)

    #region IList 

    void ICollection.CopyTo(Array array, int index) => throw new NotImplementedException();        
    bool IList.IsFixedSize => throw new NotImplementedException();
    bool IList.Contains(object value) => throw new NotImplementedException();       
    int IList.IndexOf(object value) => throw new NotImplementedException();
    void IList.Insert(int index, object value) => throw new NotImplementedException();
    void IList.Remove(object value) => throw new NotImplementedException();
    int IList.Add(object value) => throw new NotImplementedException();
    public bool IsSynchronized => throw new NotImplementedException();
    public object SyncRoot { get; } = new object();

    object IList.this[int index] {
        get => this[index];
        set => this[index] = (T) value;
    }
    #endregion
}

然后在触发按钮点击事件时设置CollectionChanged

【讨论】:

  • 感谢您的解决方案!我希望这有更多的记录。我在 MSDN 上找到的唯一文档是建议使用 IList,但没有说它是必需的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-18
相关资源
最近更新 更多