自制CheckListBox控件

虽然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,以便于您获取更多的相关知识。

时间: 2024-09-07 01:27:42

自制CheckListBox控件的相关文章

VB6.0自制Line控件时实现X1,Y1,X2,Y2属性

控件 Line控件本来是最简单的一个控件,但它太简单了,以至于不提供我们想要的一些事件,为了增强它的功能,我自己制作了一个Line控件,还 给她取名叫作MLine控件. 制作控件的方法请参看"MSDN - Visual Basic 文档 - 使用Visual Basic -部件工具指南 - 创建ActiveX部件"中的"创建一个ActiveX控件"和" 建立ActiveX控件"部分. VB自带的Line控件有X1,X2,Y1,Y2四个属性,没有L

Delphi中自制动态显示的控件

Delphi以其优秀的界面和简单的用法深受广大程序员的喜爱.笔者经过摸索,自制了一个具有动态显示特性的控件.只需在主程序中调用该控件的一个方法即可实现动态显示. 在动态显示的同时,为了不影响主程序做其他的事情,笔者采用了比较流行的线程技术. 一.方案 自制一个父类为TEdit的控件,应该有一个Text属性,能自由地输入要动态显示的内容; 并且有一个MoveShow方法,使的Text的内容能动态的显示.在主程序中创建一个线程,启动线程时,调用该控件的MoveShow方法. 二.制作控件 启动New

.Net WInform开发笔记(三)谈谈自制控件(自定义控件)_C#教程

末日这天写篇博客吧,既然没来,那就纪念一下. 这次谈谈自制控件,也就是自定义控件,先上图,再说 1.扩展OpenFileDialog,在OpenFileDialog中添加各种文件(.txt,.jpg,.excel等等)的预览功能 开发笔记(三)谈谈自制控件(自定义控件)_C#教程-winform自定义控件"> 2.重写ListBox,增加折叠.鼠标背影.分类等功能 -----------------------------分割线-------------------------------

自制网页选取本地路径控件(附源码)_实用技巧

用C#开发的一个WEB选取本地目录路径的控件,OBJECT控件嵌入网页后,会列出本地磁盘上目录列表,通过控件JS方法GetDirPath()获取选择的目录路径 代码就不贴了,直接给源码和DEMO 源码和DEMO打包下载:WebDirSelector.rar 注册和使用: 1.打开WebDirSelector解决方案2.在"项目属性->生成"里,将"为COM Interop注册"打上勾,编译后系统会自动注册DLL(或在命令行中用regsvr32注册编译好的Web

VC下自制一个MusicPlayer:调用activemovie控件

步骤如下:1.打开vc6.0,用AppWizard新建一个project(是exe那个) 2.选择"基于对话框"(第三个选项) 3.一路确定,进入下面的界面:你可以拖动各种控件了 4.但是要用的控件activemovie不在这里.解决方法:开始->运行 输入regsvr32 msdxm.ocx 4.经过上一步的操作,已经可以添加activemovie控件了,方法:刚刚建立的工程的窗口中,Project->Add to project->Components and c

2KB内存单片机上实现彩屏GUI控件库

一. 综述 嵌入式系统发展日新月异,安卓和ios已然战胜了当年雄霸天下的塞班,界面是我们特别看重的因素之一.不过你考虑过自己做一套系统,写一个界面库么?在单片机上自制系统,可以很好的锻炼编程能力和架构设计能力. 这些界面库都是在底层画点画线的驱动程序上实现的,基于我的XMOVE动作感应系统.基本具有硬件无关性.支持彩屏320*240的分辨率,由于考虑不同分辨率的开发过分复杂(想想看你需要计算每个点布局在哪个位置,这对安卓等系统都是大问题),因此我并没有太过完善的考虑过其他分辨率. 我已经写过一篇

c#-C# 用户控件 Text属性无法显示

问题描述 C# 用户控件 Text属性无法显示 请教下各位 我建立个一个空白的用户控件 没有额外的引用 添加了一个自动属性 public string Text { get; set; } 编译后 给出提示 需要隐藏 或者覆盖方法 就改为public override string Text { get; set; } 就没有额外的提示 但是编译 拖出控件后 没有Text这个属性 而其他自制的属性能正常显示 请问该如何解决 解决方案 重新编译下看看.你第二个写法没问题. 解决方案二: 额?请问什

XMOVE3.0手持终端——软件介绍(二):在2KB内存的单片机上实现的彩屏GUI控件库

一. 综述 嵌入式系统发展日新月异,安卓和ios已然战胜了当年雄霸天下的塞班,界面是我们特别看重的因素之一.不过你考虑过自己做一套系统,写一个界面库么?在单片机上自制系统,可以很好的锻炼编程能力和架构设计能力. 这些界面库都是在底层画点画线的驱动程序上实现的,基于我的XMOVE动作感应系统.基本具有硬件无关性.支持彩屏320*240的分辨率,由于考虑不同分辨率的开发过分复杂(想想看你需要计算每个点布局在哪个位置,这对安卓等系统都是大问题),因此我并没有太过完善的考虑过其他分辨率. 我已经写过一篇

银行网银为何只认IE?安全控件是关键

"中国工商银行能改进一下你们的网站吗?排名财富500强第54名的公司,网站简陋得像乡镇企业,用Firefox(火狐浏览器)和 Chrome(谷歌浏览器)都不能登录你们的系统,只能用IE(微软浏览器),还不能是IE9,得是IE6.你们不脸红吗?"日前,新浪微博上一位名为 "假装的纽约"的用户发布了这样一条微博,引起众人关注,并 纷纷吐槽. 那么到底工商银行网上银行支持哪些浏览器呢?其他银行的网站是否也有类似的情况呢?记者进行了调查.工行网银不认Firefox记者在Wi