标签:isl set get 准备 call play 程序 存储 输出
首先说说需求,有多种不同类型的UserControl用于以不同的方式显示数据,想通过在另一个view中实现某种点击选中按钮后,在数据显示view中,只让被逻辑关联的UserControl显示(Visiable),其他UserControl全部折叠(Collasped)起来。这种方式就类似于几个控件绑定到一组RadioButtonGroup中,哪个RadioButton被选中了,就显示哪部分内容。
虽然我知道有种修改template的方式,应该可以做到,但我还没深入学习到这部分。于是想了个别的招。
因为是在不同的View上,如此一来,就不能简单地通过绑定到元素的IsSelected->Visilibity的方式来实现。
那么就自己实现一个类似于RadioButtonGroup的功能。
1.首先准备一个类,用于和我的UserControl的Visilibity属性绑定。
public class IsSelectedClass { protected bool isSelected; public bool IsSelected
{
get=>isSelected; set { isSelected = value; OnPropertyChanged(nameof(IsSelected)); } } }
2.准备一个GroupList,用于存储我们加入(Add)的IsSelectedCalss对象
List<IsSelectedCalss> list = new List<IsSelectedCalss>();
3.为了有更好的扩展性和兼容性,接下来将IsSelectedCalss和List<IsSelectedCalss>重新封装为泛型形式
并且,因为IsSelected属性与UserControl的Visibility属性进行绑定,所以要实现INotifyPropertyChanged接口。
我们将RadioGroupList类视为RadioButtonGroup类,往RadioGroupList对象中添加的是继承自IsSelectedClass类的对象。
并且在将IsSelectedClass类对象添加进List的时候,订阅其PropertyChanged事件,这样我们可以在该对象的IsSelected属性值改变时收到通知,然后再处理List中的其他IsSelectedClass对象。
记得在Remove掉该对象时,要取消订阅该事件。即使这对性能影响不大,而且Remove也不常用,但对内存有一个良好的规划,是一个程序员基本的素养。
1 public class IsSelectedClass : INotifyPropertyChanged 2 { 3 protected bool isSelected; 4 public virtual bool IsSelected 5 { 6 get =>isSelected; 7 set 8 { 9 isSelected = value; 10 OnPropertyChanged(nameof(IsSelected)); 11 } 12 } 13 public event PropertyChangedEventHandler PropertyChanged; 14 15 [NotifyPropertyChangedInvocator] 16 protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 17 { 18 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 19 } 20 21 public void SetSelectedTrue() 22 { 23 this.isSelected = true; 24 } 25 } 26 27 public class RadioGroupList<T> where T : IsSelectedClass 28 { 29 List<T> list = new List<T>(); 30 31 public void AddRadioSelector(T t) 32 { 33 list.Add(t); 34 t.PropertyChanged += TSelectedPropertyChangedEventHandler; 35 36 } 37 38 private void TSelectedPropertyChangedEventHandler(object sender, PropertyChangedEventArgs e) 39 { 40 var t = sender as IsSelectedClass; 41 if (e.PropertyName == nameof(t.IsSelected)) 42 { 43 if (t.IsSelected) 44 { 45 for (int i = 0; i < list.Count; i++) 46 { 47 list[i].IsSelected = false; 48 } 49 t.SetSelectedTrue(); 50 } 51 } 52 } 53 54 public void RemoveSelector(T t) 55 { 56 if (list.Contains(t)) 57 { 58 list.Remove(t); 59 t.PropertyChanged -= TSelectedPropertyChangedEventHandler; 60 } 61 } 62 }
4.为了改进RadioGroupList<T>类的使用,添加几个类似于List的常用方法和索引器。
public void AddRangeSelector(T[] t) { foreach (var VARIABLE in t) { AddRadioSelector(VARIABLE); } } public void Clear() { foreach (var VARIABLE in list) { VARIABLE.PropertyChanged -= TSelectedPropertyChangedEventHandler; } list.Clear(); } public T this[int index] => list[index];
5.简单测试性能
因为重复遍历了List中的元素两次,所以,我生成了200个对象来测试其性能,看看这种做法会不会卡死界面。
public ShellViewModel()//构造函数,没什么好说的 { RadioGroupList<IsSelectedClass> islist = new RadioGroupList<IsSelectedClass>(); int tcount = 200;//控制循环生成对象的数目 for (int i = 0; i < tcount; i++) { islist.AddRadioSelector(new IsSelectedClass()); } islist[110].IsSelected = true; islist[111].IsSelected = true; islist[138].IsSelected = true; islist[198].IsSelected = true; for (int i = 0; i < tcount; i++) { Console.WriteLine($"{i}={islist[i].IsSelected}"); } }
最终的输出结果是,只有索引为198的值为True,其他全为False。而且程序执行得很快,几乎是启动的时候就显示出来了。
没用Timer测试,是因为,这个是给控件用的,我的控件最多也不超过10个,所以性能上足够用了。
虽然这个功能很简单,但我作为一个小菜鸟,还是蛮开心的。欢迎大家多多留言交流~
RadioGroupList<T>
C#使用List实现类似RadioButtonGroup的单选功能
标签:isl set get 准备 call play 程序 存储 输出
原文地址:http://www.cnblogs.com/wingsziye/p/7620040.html