对于前面的集合类ObjectForBinding2以及他的子类ObjectForBinding,已经可以实现通过设置ObjectForBinding2为数据源,绑定并显示ObjectForBinding的相关属性。
但是,当ObjectForBinding2有其自身多个属性需要在绑定的时候显示的话,前面的方式就没有办法做到了,因此,不能再依赖ObservableCollection<>,而是跳过直接手动实现类ObservableCollection帮我们实现的部分,也就是说,将自定义的集合类实现INotifyPropertyChanged 以及 INotifyCollectionChanged 这两个接口。
接口INotifyPropertyChanged保证了集合类的自身属性可以被绑定并呈现。
接口INotifyCollectionChanged 保证了集合类的子类的属性可以被绑定并呈现。
第一部分:
A、重新构建集合类,代码如下:
其实,从代码中可以看到,实现两个接口,实际上就是掌握触发PropertyChanged.Invoke() 以及 CollectionChanged.Invoke()这两个事件的时机。
基本原则:
1、PropertyChanged.Invoke函数要在属性更改的时候触发,而当相关属性第一次被赋值的时候,PropertyChanged将自动关联相关内容。
2、CollectionChanged.Invoke函数要在集合子类的数量或者子类属性改变的额时候触发。
B、子类的代码如下:
代码和之前的子类代码基本一样,至于需要不需要继承INotifyPropertyChanged,这要看是否对于这个子类单独作为数据源,如果是就需要继承,反之不需要。
通过集合类和子类的比较,可以看到,两个类具有一个同名的属性:No,稍后进行绑定的时候会看到这个属性的相关使用的不同效果。
C、XAML页面的代码如下:
可以看到对于同名属性No,在两个地方被指明绑定,一个是ListBox,另一个是Label,在Path属性上指定的都是No。
D、cs文件的代码如下:
最后运行的结果如下:
从结果上看,ListBox绑定的No属性显示的是子类ObjectForBinding4的No属性;而Label绑定的No属性显示的则是集合类ObjectForBinding3的No属性。
出现这样的结果,是因为:
1、对于集合控件首先寻找的是具有集合效果的属性,于是挂接的就是ObjectForBinding4的No属性。
2、对于Lable控件则会按照逻辑树的方式自上往下的寻找No属性,从父子级别来说,ObjectForBinding3是父级别的,因此当发现这个类存在No属性时候就不会再往下搜索了,因此显示的就是ObjectForBinding3的No属性。