65.9K
CodeProject 正在变化。 阅读更多。
Home

Destination Flicker Board 自定义控件

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2010年11月8日

CPOL

2分钟阅读

viewsIcon

15396

downloadIcon

299

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

Screenshot of the a destination flicker board

引言

本文介绍在不适合继承 ItemsControl 时创建 Silverlight 自定义控件的方法。该控件显示的项目数量由控件的尺寸决定,而不是数据源中的项目数量。

背景

当我开始创建此控件时,我首先继承自 ItemsControl,但很快意识到 ItemsControl 的行为并不符合我的期望。我也意识到重写一些 ItemsControl 的方法/属性也行不通。因此,我被迫创建了一个本质上是 ItemsControl ,但没有继承关系。

Using the Code

使用该控件与其他 Silverlight ItemsControl 相同。它具有 ItemsSourceDisplayMemberPath 属性,用于将数据绑定到控件。如果 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 方法和属性,但 ItemsSourceDisplayMemberPath 属性是成功绑定到 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 日:初始版本
© . All rights reserved.