yet

Dream Will Come True

 

自定义提供程序控件

提供程序控件允许您在不新建特殊类的情况下扩展现有的控件。用来执行扩展的代码(GotFocus 和 LostFocus 处理程序)加载到在运行时插入到基类中的外部类。Visual Studio .NET 中优异的设计时支持使得提供程序控件的存在几乎不被注意。

要获得数字代码和自动颜色功能,您需要编写两个提供程序控件;一个用来实现自动颜色,另一个用来实现数字模式。在最后的窗体中,只放置真正需要的提供程序。这样,不会加载不必要的代码。如果您需要组合两个或更多扩展,则可以通过将更多提供程序绑定到同一个控件来完成。

经过证明,提供程序控件在另一个方案中也极其有用。请再次考虑可更改 TextBox 控件背景颜色的扩展。如果您希望将该功能添加到 RichTextBox 和 ListBox 控件中,又该怎么办呢?如果没有提供程序,则只能创建两个新类。

提供程序控件的妙处在于它们允许您扩展多种类型的基本控件。提供程序的最终角色就是将自定义属性添加到现有控件中。扩展属性显示在 Visual Studio .NET 属性网格中。在运行时,Windows 窗体结构为提供程序生成控件,以便真正实现扩展属性。这样做以后,扩展程序控件获得对 extendee 的引用,并且可以检查类型和名称,以及读取和更新状态。

1.ToolTip 提供程序控件
2.HelpProvider 和 ErrorProvider
都属于提供程序控件

以上描述了什么是提供程序控件,现在就让我们来制作类似这样的控件.Let's go!!

扩展程序控件非常重要,其原因有两个:它们提供的替换模型可以扩展不支持类继承的现有控件。第二,巧妙地使用扩展程序控件,可以大大地限制需要为每个窗体编写的代码数量。扩展程序控件必须基于哪个公用基础来构建其功能?必须基于 IExtenderProvider 接口。

IExtenderProvider 只定义一种方法 — CanExtend。该接口按如下方式定义:

public interface IExtenderProvider 
{
    bool CanExtend(object extendee);
}

Visual Studio .NET 调用 CanExtend 以确定容器中的哪些对象应当接收扩展程序属性。提供扩展程序属性的任何组件必须实现 IextenderProvider:

public class SimpleTextBoxExtender : Component, IExtenderProvider 
{
   
}

除了扩展程序实现 IExtenderProvider 接口这一事实以外,它主要还是一个控件。因此,除了实现该接口以外,您必须让其继承控件的基本功能。但是,如果您从 Control 继承它,则该控件就不能放在组件任务栏区域中 — 只能放在窗体上。为了让其显示在组件任务栏中,请将 Component 用作基类。但是,在这两种情况下,扩展程序的总体行为不会发生太大变化。

必须用 [ProvideProperty] 属性标记扩展程序提供程序类。ProvideProperty 属性类的构造函数使用两个参数。第一个参数是要添加的属性名,第二个参数是要向其提供属性的对象的类型。

以下代码片断定义了一个扩展程序,该扩展程序向窗体上的所有文本框添加 SelectedBackColor 属性:

[ProvideProperty("SelectedBackColor", typeof(TextBox))]
class SimpleTextBoxExtender: Component, IExtenderProvider 
{
   
}

请注意,还可以将该属性声明为几乎所有组件的扩展属性 — 在属性中使用 IComponent 或 Control,而不使用 TextBox。在本例中,该实现通常包括一些这样的功能:只需通过特定类别的控件即可使其有用。

您实现 CanExtend 方法,以便它针对扩展程序要为其添加属性的每个控件返回“true”。下面是简单 TextBox 扩展程序可能的实现:

public bool CanExtend(object extendee) 
{
   return (extendee is TextBox);
}
类似的实现还捕捉任何从 TextBox 类(包括自定义类)继承的控件。
以下的代码显示了非常简单的扩展程序控件的源代码。它在控件获得焦点时实现背景颜色更改。
特别是,扩展程序定义 GetSelectedBackColor 和 SetSelectedBackColor 方法对。
它们可以由任何文本框调用,从而通过编程方式获得或设置背景颜色。另外,
该控件具备公共属性 SelectedBackColor,该属性出现在属性网格中并提供默认颜色。
请注意,如果您不使用 get/set 访问器显式实现该属性,它就不出现在属性网格中:
 1namespace Samples
 2{
 3    [ProvideProperty("SelectedBackColor"typeof(TextBox))]
 4    public class SimpleTextBoxExtender : Component, 
 5        IExtenderProvider
 6    {
 7        public SimpleTextBoxExtender()
 8        {
 9            InitializeComponent();
10
11            // Use a hashtable to track selected colors for 
12            // each extended control
13        }

14
15        public bool CanExtend(object target) 
16        {
17            return (target is TextBox);
18        }

19
20        private Color m_SelectedBackColor;
21        public Color SelectedBackColor
22        {
23            get {return m_SelectedBackColor;}
24            set {m_SelectedBackColor = value;}
25        }

26
27        private Color backupBackColor;
28        public Color GetSelectedBackColor(Control control)
29        {
30            return SelectedBackColor; 
31        }

32        
33        public void SetSelectedBackColor(Control control, Color 
34            selColor)
35        {
36            TextBox t = (TextBox) control;
37            SelectedBackColor = selColor;
38            t.GotFocus += new EventHandler(TextBox_GotFocus);
39            t.LostFocus += new EventHandler(TextBox_LostFocus);
40        }

41
42        private void InitializeComponent() 
43        {
44            SelectedBackColor = Color.Cyan;
45        }

46
47        private void TextBox_GotFocus(object sender, 
48            EventArgs e)
49        {
50            TextBox t = (TextBox) sender;
51            backupBackColor = t.BackColor;
52            t.BackColor = SelectedBackColor;
53        }

54
55        private void TextBox_LostFocus(object sender, 
56            EventArgs e)
57        {
58            TextBox t = (TextBox) sender;
59            t.BackColor = backupBackColor;
60        }

61    }

62}

63
64

private Color m_SelectedBackColor;
public Color SelectedBackColor
{
    get {return m_SelectedBackColor;}
    set {m_SelectedBackColor = value;}
}

如果您在示例应用程序中使用该控件,它就会很好地工作。但是,在按这种方式对该控件进行编码时,该控件将会过于简单并且没有太多的功能。主要缺点在于背景颜色对于所有的文本框都是唯一的。而且,挂钩事件是需要更多关注的难以处理的操作。尝试使用带有扩展程序的任何派生文本框,您将看到这个混淆结果。重要的扩展程序需要维护由绑定控件组成的表格并分别存储设置。

posted on 2005-07-20 21:51  yet  阅读(351)  评论(0编辑  收藏  举报

导航