Destination Flicker Board 自定义控件
在继承 ItemsControl 不符合要求时创建自定义控件

引言
本文介绍在不适合继承 ItemsControl
时创建 Silverlight 自定义控件的方法。该控件显示的项目数量由控件的尺寸决定,而不是数据源中的项目数量。
背景
当我开始创建此控件时,我首先继承自 ItemsControl
,但很快意识到 ItemsControl
的行为并不符合我的期望。我也意识到重写一些 ItemsControl
的方法/属性也行不通。因此,我被迫创建了一个本质上是 ItemsControl
,但没有继承关系。
Using the Code
使用该控件与其他 Silverlight ItemsControl
相同。它具有 ItemsSource
和 DisplayMemberPath
属性,用于将数据绑定到控件。如果 ItemSource
实现了 INotifyPropertyChanged
,则控件将在值更改时闪烁字符。该控件还具有一个 UpdateRow
方法,可在控件未绑定时使用。
关注点
创建自己的自定义 ItemsControl
,不继承自 ItemsControl
,并不像您想象的那么困难。您必须实现的两个依赖属性是
ItemsSource 依赖属性
public static DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(FlickerBoard),
new PropertyMetadata(new PropertyChangedCallback(OnItemsSourceChanged)));
public IEnumerable ItemsSource
{
get
{
return (IEnumerable)base.GetValue(ItemsSourceProperty);
}
set
{
if (value != ItemsSource) base.SetValue(ItemsSourceProperty, value);
}
}
private static void OnItemsSourceChanged
(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FlickerBoard table = d as FlickerBoard;
table.Bind();
}
DisplayMemberPath 依赖属性
public static DependencyProperty DisplayMemberPathProperty =
DependencyProperty.Register("DisplayMemberPath", typeof(string),
typeof(FlickerBoard), null);
public string DisplayMemberPath
{
get
{
return (string)base.GetValue(DisplayMemberPathProperty);
}
set
{
if (value != DisplayMemberPath)
base.SetValue(DisplayMemberPathProperty, value);
}
}
您可能希望它实现其他 ItemsControl
方法和属性,但 ItemsSource
和 DisplayMemberPath
属性是成功绑定到 Enumerable 数据源所必需的全部。
然而,这不仅仅是创建绑定。显示单个项目的 UIElements
也需要绑定。同样,您需要一个 DisplayMemberPath
属性,以及一个 Item
属性来维护对所表示项目的引用。如以下代码片段所示,您还需要确定项目是否实现了 INotifyPropertyChanged
。
public object Item
{
get
{
return base.GetValue(ItemProperty);
}
set
{
if (value != Item)
{
var newValue = value as INotifyPropertyChanged;
var oldValue = Item as INotifyPropertyChanged;
if (oldValue != null)
oldValue.PropertyChanged -=
new PropertyChangedEventHandler(Item_PropertyChanged);
base.SetValue(ItemProperty, value);
if (newValue != null)
newValue.PropertyChanged +=
new PropertyChangedEventHandler(Item_PropertyChanged);
else
DisplayText(this.Text);
}
}
}
void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
DisplayText(this.Text);
}
添加一些反射来获取 DisplayMemberPath
值
System.Reflection.PropertyInfo pi = Item.GetType().GetProperty(DisplayMemberPath);
就这样,创建自己的 ItemsControl
自定义控件的精髓和关键。在大多数情况下,您不需要付出这么大的努力来实现一个 ItemsControl
。只有当控件中的项目需要“填充”控件内的显示区域时,才需要这种方法。
历史
- 2010 年 11 月 8 日:初始版本