虽然CodePlex上的WPF扩展的XXX ToolKit源码中有一个CheckListBox控件,但是,就看它那源代码,也过于复杂了。并 且,我也希望自己来编写一个CheckListBox控件。
所谓CheckListBox控件嘛,就是既可以Select又可以Check的 ListBox控件。有人会说,不用写控件,自定义一个ListBoxItem的模板就行了,也确实可以这样做,不过,还是有些问题的 ,如果只是重定义ListBoxItem的模板,那仅仅是为其UI上加了个可以显示一个“勾”的东东而已,而对于逻辑是没有任何 变化。
既然要可以Select又能Check,那显然只是重定义模板是不行的。ListBoxItem类本身有一个IsSelected属性 ,指示列表项是否被选中,而且,人家在ListBox中也有一个SelectedItems属性,可以获得ListBox控件的当前选中的所有 项。
很明显,我们的CheckableListBoxItem要有一个IsChecked属性来指示列表项是否被Check,而在CheckListBox 控件上应当有一个CheckedItems属性,可以获取当前所有被Checked的项。
刚开始,我是计划让 CheckableListBoxItem从ContentControl类派生,CheckListBox从ItemsControl派生。但是,转念一想,其实这所谓的可以 Check的ListBox就是ListBox和CheckBox控件的结合体,而大多数功能与ListBox控件相似,是没有必要自己重新来写 ListBox的功能,所以,后来我决定:CheckableListBoxItem从ListBoxItem类派生,CheckListBox则从ListBox派生,但其 中的项目的容器已经不是ListBox了,而是我继承的CheckableListBoxItem类。
有一点我们要明确的,熟悉WPF的朋 友都知道,在WPF/SL/WP/Store App这一堆使用XAML布局UI的开发框架中,列表控件所获出来的项并不是项的容器,除非你 在ListBox中直接用ListBoxItem作为对象加进列表控件的集合中,不然会根据你添加的项返回对应的内容,如果你放进去的 是String,那么拿出来也是String;你放进去的是int,拿出来的也是int。
至于说为什么要这样做嘛,很多人不解 了,ListBox里面明明是放ListBoxItem的,怎么直接返回其对象了?WPF说的是啥?MVVM,既然要MVVM,当然是你在绑定了 哪个对象,取出来还是那个对象好了,这样就方便了。
好了,理论的扯完了,就上代码吧。
using System; using System.Collections.Generic; using System.Collections; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace MyListBox { [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(CheckableListBoxItem))] public class CheckListBox : ListBox { ObservableCollection<object> m_checkedItems = null; Type m_itemContainerType = typeof(FrameworkElement);//项容器的类型 public CheckListBox() { m_checkedItems = new ObservableCollection<object>(); // 从CheckListBox类附加的特性中获取项目容器的类型 var attr = this.GetType().GetCustomAttributes(typeof(StyleTypedPropertyAttribute), false); if (attr != null && attr.Length != 0) { StyleTypedPropertyAttribute sty = attr[0] as StyleTypedPropertyAttribute; if (sty != null) { this.m_itemContainerType = sty.StyleTargetType; } } } public static DependencyProperty CheckedItemsProperty = DependencyProperty.Register("CheckedItems", typeof(IList), typeof(CheckListBox), new PropertyMetadata(null)); public IList CheckedItems { get { return (IList)GetValue(CheckedItemsProperty); } } /// <summary> /// 创建项目容器 /// </summary> protected override DependencyObject GetContainerForItemOverride() { return Activator.CreateInstance(this.m_itemContainerType) as DependencyObject; } /// <summary> /// 当从项目创建项容时, /// 为项目容器注册事件处理。 /// </summary> protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { CheckableListBoxItem ckItem = element as CheckableListBoxItem; ckItem.Checked += clbitem_Checked; ckItem.UnChecked += clbitem_UnChecked; base.PrepareContainerForItemOverride(element, item); } /// <summary> /// 当项容被清空时, /// 解除事件处理程序。 /// </summary> protected override void ClearContainerForItemOverride(DependencyObject element, object item) { CheckableListBoxItem ckItem = element as CheckableListBoxItem; ckItem.Checked -= clbitem_Checked; ckItem.UnChecked -= clbitem_UnChecked; base.ClearContainerForItemOverride(element, item); } void clbitem_UnChecked(object sender, RoutedEventArgs e) { CheckableListBoxItem citem = (CheckableListBoxItem)e.Source; object value = citem.Content; m_checkedItems.Remove(value); SetValue(CheckedItemsProperty, m_checkedItems); } void clbitem_Checked(object sender, RoutedEventArgs e) { CheckableListBoxItem citem = (CheckableListBoxItem)(e.Source); object value = citem.Content; if (m_checkedItems.SingleOrDefault(o => object.ReferenceEquals(o, value)) == null) { m_checkedItems.Add(value); SetValue(CheckedItemsProperty, m_checkedItems); } } } public class CheckableListBoxItem : ListBoxItem { static CheckableListBoxItem() { DefaultStyleKeyProperty.OverrideMetadata(typeof(CheckableListBoxItem), new FrameworkPropertyMetadata(typeof(CheckableListBoxItem))); } #region 属性 public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register("IsChecked", typeof(bool), typeof(CheckableListBoxItem), new PropertyMetadata(new PropertyChangedCallback(IsCheckedPropertyChanged))); private static void IsCheckedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { CheckableListBoxItem lt = d as CheckableListBoxItem; if (lt !=null) { if (e.NewValue != e.OldValue) { bool b = (bool)e.NewValue; if (b== true) { lt.RaiseCheckedEvent(); } else { lt.RaiseUnCheckedEvent(); } } } } /// <summary> /// 获取或设置控件是否被Check /// </summary> public bool IsChecked { get { return (bool)GetValue(IsCheckedProperty); } set { SetValue(IsCheckedProperty, value); } } #endregion #region 事件 public static readonly RoutedEvent CheckedEvent = EventManager.RegisterRoutedEvent("Checked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(CheckableListBoxItem)); /// <summary> /// 当控件被Check后发生的事件 /// </summary> public event RoutedEventHandler Checked { add { AddHandler(CheckedEvent, value); } remove { RemoveHandler(CheckedEvent, value); } } void RaiseCheckedEvent() { RoutedEventArgs arg = new RoutedEventArgs(CheckableListBoxItem.CheckedEvent); RaiseEvent(arg); } public static readonly RoutedEvent UnCheckedEvent = EventManager.RegisterRoutedEvent("UnChecked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(CheckableListBoxItem)); /// <summary> /// 当控件未被Check后发生 /// </summary> public event RoutedEventHandler UnChecked { add { AddHandler(UnCheckedEvent, value); } remove { RemoveHandler(UnCheckedEvent, value); } } void RaiseUnCheckedEvent() { RaiseEvent(new RoutedEventArgs(UnCheckedEvent)); } #endregion } }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索控件
, typeof
, listbox
, using
, system
, public
, citem
, RoutedEvent
, 自制控件
EventManager
checklistbox、c checklistbox、cchecklistbox、delphi checklistbox、winform checklistbox,以便于您获取更多的相关知识。