java listbox_制作一个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 m_checkedItems = null;

Type m_itemContainerType = typeof(FrameworkElement);//项容器的类型

public CheckListBox()

{

m_checkedItems = new ObservableCollection();

// 从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); }

}

///

/// 创建项目容器

///

protected override DependencyObject GetContainerForItemOverride()

{

return Activator.CreateInstance(this.m_itemContainerType) as DependencyObject;

}

///

/// 当从项目创建项容时,

/// 为项目容器注册事件处理。

///

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);

}

///

/// 当项容被清空时,

/// 解除事件处理程序。

///

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();

}

}

}

}

///

/// 获取或设置控件是否被Check

///

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));

///

/// 当控件被Check后发生的事件

///

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));

///

/// 当控件未被Check后发生

///

public event RoutedEventHandler UnChecked

{

add { AddHandler(UnCheckedEvent, value); }

remove { RemoveHandler(UnCheckedEvent, value); }

}

void RaiseUnCheckedEvent()

{

RaiseEvent(new RoutedEventArgs(UnCheckedEvent));

}

#endregion

}

}

定义模板的XAML的核心部分如下:

接下来就是测试一下控件。

******************************************************************

lb.ItemsSource = new Student[]

{

new Student{ Name="狗", Age=30 },

new Student{ Name="兔", Age=31 },

new Student{ Name="蛇", Age=18 },

new Student{ Name="鸡", Age=22 },

new Student{ Name="猫", Age=24 },

new Student{ Name="青蛙", Age=28 },

new Student{ Name="猴", Age=19 }

};

代码不完全,但主要的我都放出来了,随后我把所有代码都上传到【资源】中,相当优惠,0积分下载。

下图是最终的结果。

7ae70c30d6fa2488d8a9c1e5e6fddc50.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值