列表内容属性
如上图,是一个列表标题排序控件,我们需要定义一个标题列表,从而让调用方可以自由的设置标题信息。
在自定义控件时,会遇到列表依赖属性,那么该如何定义呢?
下面是错误的定义方式:
1 /// <summary>
2 /// 标识 <see cref="Headers"/> 的依赖项属性。
3 /// </summary>
4 public static readonly DependencyProperty HeadersProperty = DependencyProperty.Register(
5 "Headers", typeof(List<HeaderContent>), typeof(ListViewHeader),
6 new PropertyMetadata(new List<HeaderContent>(), (d, e) => ((ListViewHeader)d).InitHeaderList()));
7
8 /// <summary>
9 /// 获取或设置表头的信息集合。
10 /// 由于这是依赖项属性,所以很难限制其不为 null,需要总是判空。
11 /// </summary>
12 public List<HeaderContent> Headers
13 {
14 get => (List<HeaderContent>)GetValue(HeadersProperty);
15 set => SetValue(HeadersProperty, value);
16
按照如上依赖属性的定义,
- 必须提供一个默认属性new List<HeaderContent>() 或者 在自定义控件初始化时设置默认列表值,不然界面调用此列表属性去添加项,界面初始化时肯定会报错~
- 在Xaml中显示时,不会报出一些错误提示信息~(虽然不影响正常启动,但是错误列表中一直显示,对有强迫症的我来说。。不可忍受)
正确的实现方案
- 定义列表依赖属性:
1 /// <summary>
2 /// 标识 <see cref="Headers"/> 的依赖项属性。
3 /// </summary>
4 public static readonly DependencyProperty HeadersProperty = DependencyProperty.Register(
5 "Headers", typeof(ListViewHeaderContentCollection), typeof(ListViewHeader),
6 new PropertyMetadata(default(ListViewHeaderContentCollection), (d, e) => ((ListViewHeader)d).InitHeaderList()));
7
8 /// <summary>
9 /// 获取或设置表头的信息集合。
10 /// 由于这是依赖项属性,所以很难限制其不为 null,需要总是判空。
11 /// </summary>
12 public ListViewHeaderContentCollection Headers
13 {
14 get => (ListViewHeaderContentCollection)GetValue(HeadersProperty);
15 set => SetValue(HeadersProperty, value);
16
- 定义列表内容集合类:
通过实现IList<T>和IList接口,可以让列表在界面调用时,可以以列表的形式添加内容。
注:将实现的接口方法修改下内容即可
1 public sealed class ListViewHeaderContentCollection : IList<HeaderContent>, IList
2 {
3 private readonly List<HeaderContent> _headContents = new List<HeaderContent>();
4 public IEnumerator<HeaderContent> GetEnumerator()
5 {
6 return _headContents.GetEnumerator();
7 }
8
9 IEnumerator IEnumerable.GetEnumerator()
10 {
11 return GetEnumerator();
12 }
13
14 public void Add(HeaderContent item)
15 {
16 _headContents.Add(item);
17 }
18
19 public int Add(object value)
20 {
21 _headContents.Add((HeaderContent)value);
22 return _headContents.Count;
23 }
24
25 public bool Contains(object value)
26 {
27 return _headContents.Contains((HeaderContent)value);
28 }
29
30 public void Clear()
31 {
32 _headContents.Clear();
33 }
34
35 public int IndexOf(object value)
36 {
37 return _headContents.IndexOf((HeaderContent)value);
38 }
39
40 public void Insert(int index, object value)
41 {
42 _headContents.Insert(index, (HeaderContent)value);
43 }
44
45 public void Remove(object value)
46 {
47 _headContents.Remove((HeaderContent)value);
48 }
49
50 void IList.RemoveAt(int index)
51 {
52 _headContents.RemoveAt(index);
53 }
54
55 object IList.this[int index]
56 {
57 get => _headContents[index];
58 set => _headContents[index] = (HeaderContent)value;
59 }
60
61 public bool Contains(HeaderContent item)
62 {
63 return _headContents.Contains(item);
64 }
65
66 public void CopyTo(HeaderContent[] array, int arrayIndex)
67 {
68 _headContents.CopyTo(array, arrayIndex);
69 }
70
71 public bool Remove(HeaderContent item)
72 {
73 return _headContents.Remove(item);
74 }
75
76 public void CopyTo(Array array, int index)
77 {
78 _headContents.CopyTo((HeaderContent[])array, index);
79 }
80
81 public int Count => _headContents.Count;
82
83 public object SyncRoot { get; }
84
85 public bool IsSynchronized { get; }
86
87 public bool IsReadOnly { get; }
88
89 public bool IsFixedSize { get; }
90
91 public int IndexOf(HeaderContent item)
92 {
93 return _headContents.IndexOf(item);
94 }
95
96 public void Insert(int index, HeaderContent item)
97 {
98 _headContents.Insert(index, item);
99 }
100
101 void IList<HeaderContent>.RemoveAt(int index)
102 {
103 _headContents.RemoveAt(index);
104 }
105
106 public HeaderContent this[int index]
107 {
108 get => _headContents[index];
109 set => _headContents[index] = value;
110 }
111
调用:
作者:唐宋元明清2188