综合应用WPF/WCF/WF/LINQ之三:采用用代码创建的方式实现CheckListBox的CustomControl

实现CheckListBox的方法很多。我们可以直接在XAML文件中的ListBox控件中,嵌入CheckBox控件。但更多的时候,我们还是希望能把它编写成一个CustomControl以方便直接使用。
  以我们的Eallies OA系统为例,实现CheckListBox的CustomControl的方法如下:
  1、在Eallies.OA.UI.Controls.Common项目中添加一个CustomControl的项目,并让其继承于System.Windows.Controls.ListBox类。
    1 using System;
    2 using System.Collections;
    3 using System.Collections.Generic;
    4 using System.Linq;
    5 using System.Text;
    6 using System.Windows;
    7 using System.Windows.Controls;
    8 using System.Windows.Data;
    9 using System.Windows.Documents;
   10 using System.Windows.Input;
   11 using System.Windows.Media;
   12 using System.Windows.Media.Imaging;
   13 using System.Windows.Navigation;
   14 using System.Windows.Shapes;
   15 
   16 namespace Eallies.OA.UI.Controls.Common
   17 {
   18     public class CheckListBox : ListBox
   19     {
   20         static CheckListBox()
   21         {
   22             DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckListBox), new FrameworkPropertyMetadata(typeof(CheckListBox)));
   23         }
   24     }
   25 }
  2、Themes目录下会自动生成Generic.xaml文件。为了不致于这个文件太过复杂,我们将关于CheckListBox的内容独立出来。在Themes目录下加入一个Resource Dictionary的项目,并更改其内容。
    1 <ResourceDictionary
    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4    xmlns:local="clr-namespace:Eallies.OA.UI.Controls.Common">
    5 
    6     <Style TargetType="{x:Type local:CheckListBox}" BasedOn="{StaticResource {x:Type ListBox}}" />
    7 
    8 </ResourceDictionary>
  3、Themes目录下的Generic.xaml文件也需要做一些修改。
    1 <ResourceDictionary
    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4    xmlns:local="clr-namespace:Eallies.OA.UI.Controls.Common">
    5 
    6     <ResourceDictionary.MergedDictionaries>
    7         <ResourceDictionary Source="/Eallies.OA.UI.Controls.Common;component/Themes/CheckListBox.xaml" />
    8     </ResourceDictionary.MergedDictionaries>
    9 
   10 </ResourceDictionary>
  4、之后,我们就可以为这个CustomControl添加自定义的内容了。CheckListBox控件需要一个用于保存列表项的属性,幸运的是,DataContext属性可以完成这点;它还需要一个用于保存已选择的列表项的属性,因此我们添加一个CheckedItems属性;为了支持通过DataContext属性或者直接AddItem的方法添加列表项,我们增加了OnPropertyChanged、AddItem、AddCheckedItem等方法。
    1 using System;
    2 using System.Collections;
    3 using System.Collections.Generic;
    4 using System.Linq;
    5 using System.Text;
    6 using System.Windows;
    7 using System.Windows.Controls;
    8 using System.Windows.Data;
    9 using System.Windows.Documents;
   10 using System.Windows.Input;
   11 using System.Windows.Media;
   12 using System.Windows.Media.Imaging;
   13 using System.Windows.Navigation;
   14 using System.Windows.Shapes;
   15 using Eallies.OA.Utility;
   16 
   17 namespace Eallies.OA.UI.Controls.Common
   18 {
   19     public class CheckListBox : ListBox
   20     {
   21         private Dictionary<intCheckListItem> _Items = new Dictionary<intCheckListItem>();
   22         private Dictionary<intCheckListItem> _CheckedItems = new Dictionary<intCheckListItem>();
   23 
   24         static CheckListBox()
   25         {
   26             DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckListBox), new FrameworkPropertyMetadata(typeof(CheckListBox)));
   27         }
   28 
   29         #region Public Properties
   30 
   31         public Dictionary<intCheckListItem> CheckedItems
   32         {
   33             get { return this._CheckedItems; }
   34             set { this._CheckedItems = value; }
   35         }
   36 
   37         #endregion
   38 
   39         protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
   40         {
   41             try
   42             {
   43                 if (e.Property.Name != "ItemsSource" && e.Property.Name != "DataContext")
   44                 {
   45                     base.OnPropertyChanged(e);
   46                 }
   47 
   48                 if (e.Property.Name == "DataContext")
   49                 {
   50                     this._Items = e.NewValue as Dictionary<intCheckListItem>;
   51                 }
   52             }
   53             catch
   54             {
   55                 throw;
   56             }
   57         }
   58 
   59         public void AddItem(bool ischecked, string content, int value)
   60         {
   61             try
   62             {
   63                 this._Items.Add(value, new CheckListItem(ischecked, content, value));
   64 
   65                 if (ischecked == true)
   66                 {
   67                     this._CheckedItems.Add(value, new CheckListItem(true, content, value));
   68                 }
   69             }
   70             catch
   71             {
   72                 throw;
   73             }
   74         }
   75 
   76         public void AddCheckedItem(string content, int value)
   77         {
   78             try
   79             {
   80                 if (this._CheckedItems.ContainsKey(value) == false)
   81                 {
   82                     this._CheckedItems.Add(value, new CheckListItem(true, content, value));
   83                 }
   84             }
   85             catch
   86             {
   87                 throw;
   88             }
   89         }
   90 
   91         public void Refresh()
   92         {
   93             try
   94             {
   95                 this.Items.Clear();
   96 
   97                 foreach (CheckListItem item in this._Items.Values)
   98                 {
   99                     CheckBox checkbox = new CheckBox();
  100 
  101                     if (this._CheckedItems.ContainsKey(item.Value) == true) checkbox.IsChecked = true;
  102                     if (this._CheckedItems.ContainsKey(item.Value) != true) checkbox.IsChecked = false;
  103                     checkbox.Content = item.Content;
  104                     checkbox.Tag = item.Value;
  105                     checkbox.Checked += new RoutedEventHandler(CheckBox_Checked);
  106                     checkbox.Unchecked += new RoutedEventHandler(CheckBox_Unchecked);
  107 
  108                     this.Items.Add(checkbox);
  109                 }
  110             }
  111             catch
  112             {
  113                 throw;
  114             }
  115         }
  116 
  117         private void CheckBox_Checked(object sender, RoutedEventArgs e)
  118         {
  119             try
  120             {
  121                 CheckBox checkbox = sender as CheckBox;
  122                 int key = checkbox.Tag.ToType<int>();
  123 
  124                 this._CheckedItems.Add(key, this._Items[key]);
  125             }
  126             catch
  127             {
  128                 throw;
  129             }
  130         }
  131 
  132         private void CheckBox_Unchecked(object sender, RoutedEventArgs e)
  133         {
  134             try
  135             {
  136                 CheckBox checkbox = sender as CheckBox;
  137                 int key = checkbox.Tag.ToType<int>();
  138 
  139                 this._CheckedItems.Remove(key);
  140             }
  141             catch
  142             {
  143                 throw;
  144             }
  145         }
  146 
  147         #region CheckListItem
  148 
  149         public class CheckListItem
  150         {
  151             private bool _IsChecked = false;
  152             private string _Content = string.Empty;
  153             private int _Value = -1;
  154 
  155             public CheckListItem(bool ischecked, string content, int value)
  156             {
  157                 this._IsChecked = ischecked;
  158                 this._Content = content;
  159                 this._Value = value;
  160             }
  161 
  162             public bool IsChecked
  163             {
  164                 get { return this._IsChecked; }
  165                 set { this._IsChecked = value; }
  166             }
  167 
  168             public string Content
  169             {
  170                 get { return this._Content; }
  171                 set { this._Content = value; }
  172             }
  173 
  174             public int Value
  175             {
  176                 get { return this._Value; }
  177                 set { this._Value = value; }
  178             }
  179         }
  180 
  181         #endregion
  182     }
  183 }
  5、现在我们可以在自己的项目中使用这个CustomControl了。首先需要更改XAML文件,添加引用:xmlns:common="clr-namespace:Eallies.OA.UI.Controls.Common;assembly=Eallies.OA.UI.Controls.Common",然后我们就可以使用这个控件了。
    1 <logical:PageBase
    2    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4    xmlns:logical="clr-namespace:Eallies.OA.UI.Controls.Logical;assembly=Eallies.OA.UI.Controls.Logical"
    5    xmlns:common="clr-namespace:Eallies.OA.UI.Controls.Common;assembly=Eallies.OA.UI.Controls.Common"
    6    x:Class="Eallies.OA.UI.User.Detail">
    7     <Grid>
    8         <Grid VerticalAlignment="Top">
    9             <common:CheckListBox Margin="0,0,0,0" Name="lstRoles" Width="180" Height="180" HorizontalAlignment="Left" VerticalAlignment="Top" />
   10         </Grid>
   11     </Grid>
   12 </logical:PageBase>
  6、后台操纵这个控件的代码就很简单了。注意如果采用AddItem的方式添加列表项,则添加完毕后需要调用Refresh方法。
    1         private void GetRoles()
    2         {
    3             RoleContractClient client = new RoleContractClient();
    4 
    5             try
    6             {
    7                 IList list = client.GetRoles();
    8 
    9                 if (list != null)
   10                 {
   11                     for (int i = 0; i < list.Count; i++)
   12                     {
   13                         RoleInfo functionInfo = list[i] as RoleInfo;
   14 
   15                         this.lstRoles.AddItem(false, functionInfo.RoleName, functionInfo.RoleId);
   16                     }
   17                 }
   18 
   19                 this.lstRoles.Refresh();
   20             }
   21             catch
   22             {
   23                 throw;
   24             }
   25             finally
   26             {
   27                 client.Close();
   28             }
   29         }







本文转自 Eallies 51CTO博客,原文链接:http://blog.51cto.com/eallies/79054,如需转载请自行联系原作者
上一篇:《从零开始学Swift》学习笔记(Day67)——Cocoa Touch设计模式及应用之MVC模式


下一篇:Meteor+Vue 从入门到放弃