1. 程式人生 > >C#使用List實現類似RadioButtonGroup的單選功能

C#使用List實現類似RadioButtonGroup的單選功能

輸出 virtual += ber images 界面 private 即使 strong

首先說說需求,有多種不同類型的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的單選功能