用户控件提供了一种创建和重用自定义图形界面的方法。用户控件本质上是具有可视化表示形式的组件。因此,它可能包含一个或多个 Windows 窗体控件、组件或代码块,它们能够通过验证用户输入、修改显示属性或执行作者所需的其他任务来扩展功能。可以按照与其他控件相同的方式,将用户控件置于 Windows 窗体中。在本演练的第一部分,创建一个名为 ctlClock 的简单用户控件。在本演练的第二部分通过继承扩展 ctlClock 的功能。
创建项目
创建新的项目时应指定其名称,以设置根命名空间、程序集名称和项目名称,并确保默认组件将位于正确的命名空间中。
创建 ctlClockLib 控件库和 ctlClock 控件
- 在“文件”菜单上,指向“新建”,然后选择“项目”以打开“新建项目”对话框。
- 从“C# 项目”列表中选择“Windows 控件库”项目模板,然后在“名称”框中键入 ctlClockLib。
注意 “Windows 控件库”模板在 Visual C# .NET 的标准版中不可用。有关更多信息,请参见 Visual C# 标准版的功能。
默认情况下,项目名称 ctlClockLib 也被分配到根命名空间中。根命名空间用于限定程序集中的组件名。例如,如果两个程序集都提供名为 ctlClock 的组件,则可以使用
ctlClockLib.ctlClock
指定 ctlClock 组件。在解决方案资源管理器中,右击“UserControl1”并从快捷菜单中选择“查看代码”。 - 找到 Class 语句
public class UserControl1
,将 UserControl1 更改为 ctlClock 以更改组件的名称。注意 默认情况下,用户控件从系统提供的 UserControl 类继承。 UserControl 类提供所有用户控件要求的功能,并实现标准方法和属性。
- 找到构造函数 public UserControl1(),将 UserControl1 更改为 ctlClock。
- 在解决方案资源管理器中,单击“UserControl1”,然后在“属性”窗口中,将 FileName 属性更改为 ctlClock.cs。
- 从“文件”菜单中,选择“全部保存”来保存项目。
将 Windows 控件和组件添加到用户控件
可视化界面是用户控件的基本部分。这种可视化界面是通过将一个或多个 Windows 控件添加到“用户控件设计器”中实现的。在下面的演示中,将向用户控件中加入 Windows 控件,并编写代码以实现功能。
将标签和计时器添加到用户控件中
- 在解决方案资源管理器中,右击“ctlClock.cs”,然后选择“视图设计器”。
- 在工具箱中,单击“Windows 窗体”选项卡,然后双击 label。
名为 label1 的标签控件被添加到用户控件设计器上的控件中。
- 在设计器中,单击 label1。在“属性”窗口中,设置下列属性。
属性 更改为 Name lblDisplay Text (空白) TextAlign MiddleCenter Font.Size 14 - 在“工具箱”中,单击“Windows 窗体”,然后双击“计时器”。
因为计时器是个组件,所以它在运行时没有可视化的表示形式。因此,它不与其他控件一起出现在“用户控件设计器”上,而是出现在组件栏中。
- 在组件栏中,单击 timer1,并将 Interval 属性设置为 1000,将 Enabled 属性设置为 true。
Interval 属性控制计时器组件的刻度频率。timer1 每走过一个刻度,它都会运行一次 Timer1_Tick 事件中的代码。interval 表示前后两次刻度之间的毫秒数。
- 在组件栏中,双击 timer1 以转到 ctlClock 的 timer1_Tick 事件。
- 将该代码修改为类似如下所示的代码示例。请确保将访问修饰符从 private 更改为 protected:
protected void timer1_Tick(object sender, System.EventArgs e) { // Causes the label to display the current time lblDisplay.Text = DateTime.Now.ToLongTimeString(); }
这些代码将使得当前时间显示在 lblDisplay 中。因为 timer1 的间隔设置为 1000,所以该事件每隔 1000 毫秒激发一次,从而每隔一秒就更新一次当前时间。
- 用 virtual 关键字修改该方法使其可重写。有关更多信息,请参见本主题的下一节“从用户控件继承”。
protected virtual void timer1_Tick(object sender, System.EventArgs e)
- 从“文件”菜单中,选择“全部保存”来保存项目。
将属性添加到用户控件中
现在,clock 控件封装了 Label 控件和 Timer 组件,每个都有其自己的继承属性组。尽管您的控件的后续用户无法访问这些控件的个别属性,但可以通过编写适当的代码块来创建和公开自定义属性。在下面的章节中,您将向控件中添加属性,这些属性使用户能够更改背景和文本的颜色。
将属性添加到用户控件中
- 在解决方案资源管理器中,右击“ctlClock.cs”,然后从快捷菜单中单击“查看代码”。
控件的代码编辑器打开。
- 找到 public class ctlClock 语句。在开始的 { 后面,键入:
private Color colFColor; private Color colBColor;
这些语句会创建私有变量,用来存储要创建的属性的值。
- 在步骤 2 中的变量声明下方键入以下代码:
// Declares the name and type of the property. public Color ClockBackColor // Retrieves the value of the private variable colBColor. { get { return colBColor; } // Stores the selected value in the private variable colBColor, and // updates the backcolor of the label control lblDisplay. set { colBColor = value; lblDisplay.BackColor = colBColor; } } // Provides a similar set of instructions for the forecolor. public Color ClockForeColor { get { return colFColor; } set { colFColor = value; lblDisplay.ForeColor = colFColor; } }
前述的代码使两个自定义属性(ClockForeColor 和 ClockBackColor)可用于该控件后面的用户。Get 和 Set 语句提供属性值的存储和检索,以及提供实现适合于属性的功能的代码。
- 从“文件”菜单中,选择“全部保存”来保存项目。
测试控件
控件不是独立的应用程序,它们必须寄宿在容器中。为了测试控件,必须提供一个在其中运行该控件的测试项目。在本节中,将生成控件并在 Windows 窗体中测试它。
生成控件
- 在“生成”菜单上单击“生成”。
创建测试项目
- 在“文件”菜单上,指向“添加项目”,然后单击“新建项目”以打开“添加新项目”窗口。
- 单击“Windows 应用程序”,然后在“名称”框中,键入 Test。
- 在解决方案资源管理器中,右击测试项目的“引用”节点。单击“添加引用”,显示“添加引用”对话框。
- 单击标记为“项目”的选项卡。用户控件项目将在“项目名称”下列出。
- 双击您的项目。
注意,此时该项目显示在“选定的组件”窗口中。
在添加引用之后,可以将控件置于您的窗体中。
测试控件
- 在“工具箱”中,单击“我的用户控件”,然后向下滚动,直到显示表示 ctlClock 的控件图标为止。
- 双击 ctlClock 图标。
现在,您的控件的副本被添加到窗体中。请注意,它显示当前时间,并且每秒更新一次。
- 在工具箱中,选择该图标,然后将鼠标移动到您的窗体上。
- 按住鼠标左键,同时在窗体上移动鼠标。
控件的另一个副本被拖放到窗体上。可以根据需要将任意数目的计时器副本添加到您的窗体上。
- 在设计器中,单击 ctlClock 的实例之一。
该实例的属性显示在“属性”窗口中。
- 在“属性”窗口中,找到 ClockBackColor 属性,然后选择属性以显示调色板。
- 通过单击某个颜色来选择它。
控件的背景颜色更改为您选择的颜色。
- 使用类似的事件序列来验证 ClockForeColor 属性的功能是否与预期的一样。
在本节中,您已经知道组件和 Windows 控件如何与代码和打包结合,以用户控件的形式提供自定义功能。您已经学会在用户控件中公开属性,以及如何在完成后测试控件。在下一节中,您将学习如何将 ctlClock 用作基来构造继承的用户控件。
从用户控件中继承
在上一节中,您已经学会如何将 Windows 控件、组件和代码组合成可重用的用户控件。现在,您的用户控件可以用作生成其他控件的基础。从基类派生类的过程称为“继承”。在本节中,将创建称为 ctlAlarmClock 的用户控件。此控件将从其父控件 ctlClock 中派生。您将学习通过重写父级方法并添加新的方法和属性来扩展 ctlClock 的功能。
创建继承的控件
创建继承控件的第一步是从它的父控件派生。该操作创建一个新控件,它具有父控件的全部属性、方法和图形特征,但也可以用作添加新功能或修改过的功能的基础。
创建继承的控件
- 在解决方案资源管理器中,单击 ctlClockLib。
- 从“项目”菜单中,选择“添加继承的控件”。
“添加新项”窗口打开,这时“继承的用户控件”已选中。
- 在“名称”框中,键入 ctlAlarmClock.cs,然后单击“打开”。
“继承选择器”窗口出现。
- 在“组件名称”下,双击 ctlClock。
- 在解决方案资源管理器中,浏览当前项目。注意,已添加一个称为 ctlAlarmClock 的文件。
添加 Alarm 属性
将属性添加到继承的控件的方法与添加到用户控件的方法相同。现在将使用属性声明语法向控件中添加两个属性:AlarmTime 和 AlarmSet,前者将存储发出警报的日期和时间值,后者将指示是否设置了警报。
将属性添加到用户控件中
- 在解决方案资源管理器中,右击 ctlAlarmClock 并选择“查看代码”。
- 找到 public class 语句。注意,控件从 ctlClockLib.ctlClock 继承。在 { 语句下面键入下列代码:
private DateTime dteAlarmTime; private bool blnAlarmSet; // These properties will be declared as public to allow future // developers to access them. public DateTime AlarmTime { get { return dteAlarmTime; } set { dteAlarmTime = value; } } public bool AlarmSet { get { return blnAlarmSet; } set { blnAlarmSet = value; } }
添加到控件的图形界面
继承的控件具有可视化的界面,该界面与它从中继承的控件的界面完全相同。它与其父控件拥有相同的构成控件,但除非将构成控件的属性特别公开,否则它们将不可用。可以向继承的用户控件的图形界面进行添加,方法与向任何用户控件进行添加时相同。若要继续向您的警报时钟的可视化界面进行添加,请您添加一个 label 控件,它将在警报响起时闪烁。
添加 label 控件
- 在解决方案资源管理器中,右击 ctlAlarmClock,并从快捷菜单中选择“视图设计器”。
ctlAlarmClock 的设计器在主窗口中打开。
- 单击该控件的显示部分,并查看“属性”窗口。
注意,当显示所有属性时,属性是浅灰色的。这表明这些属性是 lblDisplay 所固有的,因而不能在属性窗口中修改或访问。默认情况下,包含在用户控件中的控件是 private,其属性无论如何都无法访问。
提示 如果希望用户控件后面的用户可以访问其内部控件,则将其声明为 public 或 protected。这样就可以使用适当的代码,设置和修改包含在用户控件内的控件的属性。
- 将一个 Label 控件添加到您的用户控件。
- 使用鼠标移动该 label 控件,使它紧靠在显示框之下。在“属性”窗口中,设置以下属性:
属性 设置 Name lblAlarm Text Alarm! TextAlign Middle Center Visible false
添加警报功能
在前面的章节中,已经添加了一些属性和一个控件,它们将启用用户控件中的警报功能。在本节中,将添加代码以比较当前时间和警报时间,如果两者相同,则警报会闪烁。通过重写 ctlClock 的 Timer1_Tick 方法并将其他的代码添加到其中,可以在扩展 ctlAlarmClock 功能的同时仍保留 ctlClock 的固有功能。
重写 ctlClock 的 timer1_Tick 方法
- 在代码编辑器中,找到
private bool blnAlarmSet;
语句。在它之后,紧接着添加下列语句:private bool blnColorTicker;
- 在代码编辑器中,在类的结尾找到 }。
- 在 } 之前,添加下列代码:
protected override void timer1_Tick(object sender, System.EventArgs e) { // Calls the Timer1_Tick method of ctlClock. base.timer1_Tick(sender, e); // Checks to see if the Alarm is set. if (AlarmSet == false) return; else // If the date, hour and minute of the alarm time are the same as // now, flash! { if (AlarmTime.Date == DateTime.Now.Date && AlarmTime.Hour == DateTime.Now.Hour && AlarmTime.Minute == DateTime.Now.Minute) { // Makes lblAlarmVisible, and changes the backcolor based on // the value of blnColorTicker. The backcolor of the label // will flash once per tick of the clock. lblAlarm.Visible = true; if (blnColorTicker == false) { lblAlarm.BackColor = Color.Red; blnColorTicker = true; } else { lblAlarm.BackColor = Color.Blue; blnColorTicker = false; } } else { // Once the alarm has sounded for a minute, the label is made // invisible again. lblAlarm.Visible = false; } } }
添加此代码将完成几项任务。Override 语句指示控件使用此方法替换从基控件继承的方法。此方法被调用时,它通过调用 base.timer1_Tick 语句来调用它重写的方法,从而确保在该控件中重新产生原始控件包含的所有功能。然后,它运行附加代码以合并警报功能。当触发警报时,闪烁的 label 控件将出现。
警报时钟控件已经基本完成。剩下的唯一事情是实现关闭它的方法。为此,将向 lblAlarm_Click 方法中添加代码。
实现关闭方法
- 在解决方案资源管理器中,右击“ctlAlarmClock.cs”,然后单击“视图设计器”。
设计器打开。
- 将一个按钮添加到控件中。按以下方式设置该按钮的属性:
属性 值 Name btnAlarmOff Text Disable Alarm - 在设计器中,双击 btnAlarmOff。
代码编辑器打开并显示 private void btnAlarmOff_Click 行。
- 修改此方法,使其类似于:
private void btnAlarmOff_Click(object sender, System.EventArgs e) { // Turns off the alarm AlarmSet = false; // Hides the flashing label lblAlarm.Visible = false; }
- 从“文件”菜单中,选择“全部保存”来保存项目。
测试继承的控件
与标准用户控件一样,继承的用户控件不能独立存在,而必须寄宿在窗体或其他容器中。由于 ctlAlarmClock 的功能更加深入,因此需要附加代码以对其进行测试。在本节中,将编写一个简单的程序来测试 ctlAlarmClock 的功能。将编写代码以设置和显示 ctlAlarmClock 的 AlarmTime 属性,而且将测试其继承功能。
生成一个测试窗体并将您的控件添加到该窗体
- 在解决方案资源管理器中,单击 ctlClockLib。在“生成”菜单上,选择“生成 ctlClockLib”。
- 将一个新的“Windows 应用程序”项目添加到该解决方案中,并将其命名为 Test2。
- 在解决方案资源管理器中,右击测试项目的“引用”节点。单击“添加引用”以显示“添加引用”窗口。单击标记为“项目”的选项卡。项目将在“项目名称”下列出。双击该项目,并注意该项目此时出现在“选定的组件”窗口中。
- 在工具箱中,单击“我的用户控件”。
- 向下滚动,直到 ctlAlarmClock 的图标出现。
- 双击 ctlAlarmClock,将 ctlAlarmClock 一个副本添加到窗体中。
- 在工具箱中,定位并双击 DateTimePicker 以将一个 DateTimePicker 控件添加到窗体中,并通过双击 Label 添加一个 Label 控件。
- 使用鼠标将这些控件放置在窗体上合适的位置。
- 按以下方式设置这些控件的属性:
控件 属性 值 label1 Text (保留为空白) Name lblTest dateTimePicker1 Name dtpTest Format Time - 在设计器中,双击 dtpTest。
代码编辑器打开并显示
private void dtpTest_ValueChanged
。 - 将该代码修改为类似如下所示:
private void dtpTest_ValueChanged(object sender, System.EventArgs e) { ctlAlarmClock1.AlarmTime = dtpTest.Value; ctlAlarmClock1.AlarmSet = true; lblTest.Text = "Alarm Time is " + ctlAlarmClock1.AlarmTime.ToShortTimeString(); }
- 在解决方案资源管理器中,右击 Test2,然后从快捷菜单中选择“设为启动项目”。
- 从“调试”菜单中选择“启动”。
测试程序启动。注意,当前时间在 ctlAlarmClock 控件中被更新,并且启动时间显示在 DateTimePicker 控件中。
- 单击 DateTimePicker,其中显示小时的分钟值。
- 使用键盘设置一个分钟值,使它比 ctlAlarmClock 显示的当前时间快一分钟。
警报设置的时间显示在 lblTest 中。
- 等候显示的时间到达警报设置时间。
当显示时间到达设置警报的时间时,lblAlarm 将会闪烁。单击 btnAlarmOff 关闭警报。您现在可以重置警报。
本演练涉及了一些关键概念。您已经学会通过将控件和组件组合到用户控件容器中来创建用户控件。您还已经学会将属性添加到控件,以及编写代码以实现自定义功能。在第二节中,您学会了通过继承来扩展给定用户控件的功能,以及通过重写这些方法来更改宿主方法的功能。
via http://msdn.microsoft.com/zh-cn/library/cc438236(v=vs.71).aspx