代码之家  ›  专栏  ›  技术社区  ›  Jose

ObservableCollection PropertyChanged事件

  •  8
  • Jose  · 技术社区  · 15 年前

    好的,所以我要子类 ObservableCollection 向其中添加属性。不幸的是 PropertyChanged 事件受保护。基本上,我想将其子类化为 SelectedItem 我可以绑定到我的MVVM WPF应用程序中的列表。

    这是我班的框架:

    public class SelectableList<T> : ObservableCollection<T>
    {
        public T SelectedItem {get;set;}
    }
    

    但我不能这样做:

    SelectableList<int> intList = new SelectableList<int>();
    intList.PropertyChanged += new PropertyChangedEventHandler(intList_Changed);
    

    因为访问限制。这使我提出了一个更深层次的问题。如何通知用户界面 属性更改 事件(如Count属性)而我无法在代码隐藏中执行?

    我的头在转,有人能开导我吗?

    4 回复  |  直到 8 年前
        1
  •  10
  •   Will    13 年前
    SelectableList<int> intList = new SelectableList<int>();
    ((INotifyPropertyChanged)intList).PropertyChanged += 
        new PropertyChangedEventHandler(intList_Changed);
    

    可观测采集 implements INotifyPropertyChanged explicitly 这意味着您必须先将实例强制转换到接口,然后才能访问接口的方法、属性和事件。至于为什么要这样做,我不知道。这个 Binding markup extensio n不“知道”可观察的集合或任何其他类型。它检查类型以查看它们是否实现或扩展特定的接口/基类(INPC、INCC、DependencyObject等),因此不关心接口是否显式实现。

        2
  •  8
  •   jpierson    11 年前

    ObservableCollection(int.net 3.5)似乎在 interesting way .

    protected event PropertyChangedEventHandler PropertyChanged;
    
    event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged;
    

    这意味着 属性更改 事件可能只用于内部实现。其他的 InotifyPropertyChanged.PropertyChanged 事件实际上实现了 InotifyProperty已更改 接口作为 explicit interface . 奇怪的是,在可观察的收集中,我没有看到 InotifyPropertyChanged.PropertyChanged 实际上是凸起的。这可能表明这是.NET 3.5中的一个错误,尽管我没有测试以确认是否在将项添加到集合时引发属性更改事件进行计数,但这似乎是它应该如何工作的。

    在.NET 4.0实现中,似乎 InotifyPropertyChanged.PropertyChanged 相反,事件挂接到受保护的 属性更改 可能是错误修复的事件。这也可能是因为 differences in how auto event implementations are handled in .NET 4.0 .

    更正: 我已经证实 InotifyPropertyChanged.PropertyChanged 事件是由ObservableCollection引发的,因此我基于使用Reflector查看ObservableCollection实现的结果所做的上述假设一定是不准确的。我的猜测是反射镜在做一些奇怪的事情,我还没有证据证明这一点。

    因此,要让你的例子起作用,你需要写一篇文章来让它起作用,就像威尔在他的答案中所演示的那样。

    SelectableList<int> intList = new SelectableList<int>();
    ((INotifyPropertyChanged)intList).PropertyChanged += 
        new PropertyChangedEventHandler(intList_Changed);
    

    很有趣,对吧?使用显式接口主要是为了避免给定接口所需的成员之间不可避免的冲突,但在某种意义上,它们可以用来隐藏成员的存在。

    如果要为在子类中引入的自定义属性引发属性更改事件,请查看覆盖和/或调用受保护的 OnProperty已更改 ObservableCollection也实现的方法。这种技术是一种被广泛采用的标准,允许子类在不访问底层事件委托的情况下引发事件或处理事件。通常情况下,最好也使用这种技术,而不是将子类挂接事件处理程序挂接到它自己的基类事件。有关更多示例,请查看如何在WinForms和WPF中实现各种控件中的事件。

        3
  •  1
  •   Somnath    12 年前

    我试图在

    public class ResultCollection<T> : ObservableCollection<T>
    {
    
            Boolean _val;
            public Boolean Val
            {   
                get
                {   
                    return _val;
                }
                set
                {   
                    _val= value;
                    OnPropertyChanged(new PropertyChangedEventArgs("Val"));
                }
            }
    }
    

    我真的没注意到 属性更改 定义为 受保护的 . 最后将val属性移到了ViewModel。

        4
  •  0
  •   micahtan    15 年前

    用户界面可以也确实收到通知。这是一个限制 只是 使用ObservableCollection,它将PropertyChanged事件定义为受保护。

    fwiw,我认为你最好把ObservableCollection单独放在一边,然后在你的虚拟机中添加另一个属性。