“扩展程序提供程序”是一种为其他组件提供属性的组件。例如,将一个 ToolTip 组件添加到一个窗体后,该组件将向该窗体上的每个控件提供名为 ToolTip 的属性。ToolTip 属性然后会出现在任何附加的 PropertyGrid 控件中。在设计时,您可以设置此属性的值。
扩展程序提供程序提供的属性实际驻留在扩展程序提供程序对象本身,因此并不是它修改的组件的真正属性。在设计时,该属性将出现在任何附加到正在修改的组件的 PropertyGrid 中。不过,在运行时,您无法通过组件自身来访问属性。您需要对 ToolTip 组件调用 GetToolTip 方法。
创建自己的IExtenderProvider 组件
所有的扩展程序提供程序必须实现IExtenderProvider 接口和继承Component基类,IExtenderProvider 接口位于System.ComponentModel命名空间,其声明如下:
public interface IExtenderProvider
{
bool CanExtend(object extendee);
}
此接口只有一个方法bool CanExtend(object),这个方法告诉VS.net设计器是否将扩展属性显示在给出控件的属性窗口中。实现了IExtenderProvider接口的组件称为“扩展程序提供程序”。DotNet 2.0中自带的ToolTips和ErrorProvider就是二个典型的扩展程序提供程序。如将ToolTips控件添加到窗体中后,TextBox1控件便多了个ToolTips on toolTips1的属性。
这时候我们注意到IExtenderProvider接口并没有提供任何有关扩展属性的消息,那vs.net设计器是如何知道扩展程序提供什么样的扩展属性给控件呢?是ProvideProperty特性(Attribute)!设计器会在实现IExtenderProvider接口的组件中寻找所有的ProvideProperty特性,ProvideProperty特性标明了扩展程序给什么类型的控件提供什么扩展扩展属性的信息。
[ProvideProperty("<Name>", typeof(TextBox))]
public class TextboxExtender : Component, IExtenderProvider
{...}
一旦在控件上声明了ProvideProperty特性,就需要在控件中提供名为Get<Name>和Set<Name>的二个Public方法。Get<Name>方法有一个参数,参数类型和ProvideProperty特性中定义的类型相同,返回此组件此属性的值。Set<Name>方法带两个参数,第一个参数是ProvideProperty特性中指定的组件类型,第二个参数是要设置给扩展属性的数据,类型和Get<Name>方法返回的数据类型相同。
编程实战:我们准备在应用程序添加一个扩展程序提供程序,名字叫“FlybyText”,该扩展程序提供程序的作用是,当鼠标经过菜单项(ToolStripMenuItem)时,会在状态栏(ToolStripStatusLabel)中显示相关信息。源码如下:
[ProvideProperty("FlybyText", typeof(ToolStripMenuItem))]
public class FlybyTextProvider:Component,IExtenderProvider
{
public FlybyTextProvider()
{
}
private Hashtable _flybyTable = new Hashtable();
[Browsable(false)]
public Hashtable FlybyTable
{
get { return this._flybyTable; }
}
private ToolStripStatusLabel _statusLabel = null;
public ToolStripStatusLabel StatusLabel
{
get { return _statusLabel; }
set { _statusLabel = value; }
}
private string _originalText = string.Empty;
public string OriginalText
{
get { return _originalText; }
private set { _originalText = value; }
}
public void SetFlybyText(ToolStripMenuItem item, string text)
{
if (string.IsNullOrEmpty(text))
{
if (FlybyTable.Contains(item))
{
FlybyTable.Remove(item);
item.MouseEnter -= OnMouseEnter;
item.MouseLeave -= OnMouseLeave;
}
}
else
{
FlybyTable[item] = text;
item.MouseEnter += OnMouseEnter;
item.MouseLeave += OnMouseLeave;
}
}
public string GetFlybyText(ToolStripMenuItem item)
{
return FlybyTable[item] as string;
}
#region 事件
private void ShowFlyby(object item)
{
string flybyText = FlybyTable[item] as string;
if (!string.IsNullOrEmpty(flybyText) && StatusLabel != null)
{
OriginalText = StatusLabel.Text;
StatusLabel.Text = flybyText;
}
}
private void RevertFlyby(object item)
{
if (StatusLabel != null)
{
StatusLabel.Text = OriginalText;
OriginalText = string.Empty;
}
}
private void OnMouseEnter(object sender, EventArgs e)
{
ShowFlyby(sender);
}
private void OnMouseLeave(object sender, EventArgs e)
{
RevertFlyby(sender);
}
#endregion
#region IExtenderProvider 成员
public bool CanExtend(object extendee)
{
return extendee is ToolStripMenuItem;
}
#endregion
}
使用时,该程序会以组件的形式出现
添加后,会在所有的ToolStripMenuItem菜单的属性面板上出现扩展属性
运行效果: