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 日:初始版本



