使用智能标记功能自定义用户控件






4.70/5 (14投票s)
本文解释了如何为用户控件添加智能标记功能。
引言
本文解释了如何为用户控件添加智能标记功能。众所周知,用户控件在 Windows Forms 应用程序中通常用于实现可重用性,从而为项目提供各种功能。添加到其中的智能标记功能将为开发人员带来额外的好处。他们可以在设计时根据项目中的不同窗体,通过设置各种属性和行为来定制用户控件。本文还通过一个简单易懂的示例应用程序演示了这一概念,详细介绍了构建必要组件的步骤。
设计器服务
.NET 设计时架构提供了在设计模式下自定义组件和控件的行为和显示方式。它允许开发人员为组件和控件构建自定义的设计时扩展。开发人员可以提供自定义设计时行为、值配置界面、属性初始化代码生成,并利用设计时环境提供的服务。
大多数自定义组件和控件都是可设计的,这意味着它们具有用户可以在设计时通过图形用户界面 (UI) 配置的设置。这些设置通常会影响组件在运行时实例。例如,添加对程序集 System.Design
的引用并导入 System.ComponentModel.Design
命名空间。您可以使用此命名空间中的类型为任何 Windows Forms 控件或组件创建智能标记或自定义设计器。
设计时架构
主要有三种设计时支持提供者:设计器、类型转换器和 UI 类型编辑器。我将简要描述上述架构中仅与本文相关的几个组件。
属性将类型或类型成员与扩展设计时行为的类相关联。例如,DesignerAttribute
将类型与设计器相关联。
设计器可以自定义组件在设计时的行为,包括其外观、初始化以及与用户的交互。设计器可以添加、删除或替换在选定组件的属性浏览器中列出的属性。设计器可以提供用户定义的可以链接到特定组件事件的方法,或者可以从自定义菜单命令或 DesignerVerb 执行的方法。
在 System.ComponentModel.Design
命名空间中,DesignerActionList
类提供了用于定义用于创建智能标记面板的项列表的基类。
设计器命令和 DesignerAction
对象模型为您提供了一种通用的方法来在设计时为组件指定一组操作。然后,用户可以从设计图面访问这些操作,通常是通过单击组件的智能标记图标()并从智能标记面板中选择一个提供的操作。此模型统一了设计器向用户提供命令的各种方式。
智能标签
智能标记功能使组件和控件能够向用户显示上下文敏感的信息和命令。智能标记可以被视为设计器动词的替代,因为您可以选择在智能标记面板以及与组件或控件关联的快捷菜单中显示智能标记项。
Designer Command Classes,例如 DesignerVerb
和 DesignerActionItem
,允许我们在开发组件和控件时以菜单命令的形式公开设计器命令。
DesignerAction 对象模型
以下是实现 DesignerAction
对象模型的重要类列表。
DesignerActionItem
:表示智能标记面板上的面板项。DesignerActionList
:定义用于创建智能标记面板的项列表。DesignerActionService
:建立一个设计时服务,用于管理组件的DesignerActionItem
对象集合。DesignerActionTextItem
:表示面板上的静态文本项。派生自DesignerActionItem
。DesignerActionPropertyItem
:表示与派生自DesignerActionList
的类中的属性相关联的面板项。派生自DesignerActionItem
。DesignerActionMethodItem
:表示与派生自DesignerActionList
的类中的方法相关联的面板项。派生自DesignerActionItem
。DesignerActionHeaderItem
:表示智能标记面板上的静态标题项。派生自DesignerActionTextItem
。
示例应用程序演练:带智能标记的用户控件
现在,在理解了设计时类之后,我将继续开发一个附加了智能标记的 UserControl
。在此应用程序中,我们在 ListBox
中有一个包含城市名称列表的用户控件,用户可以通过在智能标记面板命令中提供的文本框中键入几个字符来过滤城市。
用户还可以使用智能标记面板中的菜单命令设置用户控件的背景和前景色。因此,在此用户控件中内置的智能标记功能具有三个动词,用于获取/设置用户控件的 BackColor
和 ForeColor
属性,以及其中标签控件的 Text
属性,以过滤城市名称。
步骤 1:创建一个 Windows Forms 应用程序,并向其中添加一个名为 MyControl
的用户控件。
步骤 2:向 UserControl
表面添加一个标签控件。将其 Name
属性设置为“label2
”,将其 Text
属性设置为“List of Cities starting with:”。
步骤 3:添加另一个名为“label1
”的标签。
步骤 4:添加一个 ListBox
控件,并将其命名为 listBox1
。
步骤 5:删除类 MyControl
的 VS 生成代码,并将以下代码添加到定义所需属性的用户控件中。请注意,该类已附加了 Designer 属性。
[Designer(typeof(myControlDesigner))]
public partial class MyControl : UserControl
{
public MyControl()
{
InitializeComponent();
}
public override Color BackColor
{
get
{
return base.BackColor;
}
set
{
base.BackColor = value;
}
}
public override Color ForeColor
{
get
{
return base.ForeColor;
}
set
{
base.ForeColor = value;
}
}
public string LabelText
{
get
{
return this.label1.Text;
}
set
{
this.label1.Text = value;
}
}
}
步骤 6:在 MyControl
的 Load
事件处理程序中,在声明用于存储城市名称列表的数组后,添加以下代码。
string[] cities;
private void MyControl_Load(object sender, EventArgs e)
{
cities = new string[] { "NewYork", "Mumbai", "Belgrade",
"Los Angeles", "Chennai", "New Delhi", "Madrid", "Chicago",
"Las Vegas", "Bangalore", "Sydney", "Melbourne", "Beijing",
"Calcutta", "Milan", "Austin", "Brisbane" };
}
步骤 7:在 label1
控件的 TextChanged
事件处理程序中,添加以下代码,该代码会过滤城市名称并填充列表框。它使用 LINQ 查询城市数组,并过滤掉以智能标记面板中键入的字符开头的名称。需要注意的是,当 MyControl
的 LabelText
属性更改时,label1
会更新。
private void label1_TextChanged(object sender, EventArgs e)
{
listBox1.Items.Clear();
IEnumerable filtered =
from a in cities
where a.StartsWith(label1.Text)
orderby a
select a;
if (filtered.Count() > 0)
listBox1.Items.AddRange(filtered.ToArray());
}
步骤 8:现在,必须为 MyControl
定义 ControlDesigner
类,如步骤 5 中的属性所示。此类 myControlDesigner
已附加了 PermissionSet
属性,因为它需要完全权限才能访问智能标记功能。
[System.Security.Permissions.PermissionSet
(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class myControlDesigner : System.Windows.Forms.Design.ControlDesigner
{
private DesignerActionListCollection actionLists;
// Use pull model to populate smart tag menu.
public override DesignerActionListCollection ActionLists
{
get
{
if (null == actionLists)
{
actionLists = new DesignerActionListCollection();
actionLists.Add(new myControlActionList(this.Component));
}
return actionLists;
}
}
}
步骤 9:以下代码在用户控件的构造函数中创建了智能标记菜单操作/命令列表。DesignerActionList
类已被继承,并实现了方法以创建智能标记项。
public class myControlActionList : System.ComponentModel.Design.DesignerActionList
{
private MyControl colUserControl;
private DesignerActionUIService designerActionUISvc = null;
//The constructor associates the control with the smart tag list.
public myControlActionList(IComponent component)
: base(component)
{
this.colUserControl = component as MyControl;
// Cache a reference to DesignerActionUIService,
// so the DesigneractionList can be refreshed.
this.designerActionUISvc = GetService(typeof(DesignerActionUIService))
as DesignerActionUIService;
}
.....
.....
// Implementation of this abstract method creates smart tag items,
// associates their targets, and collects into list.
public override DesignerActionItemCollection GetSortedActionItems()
{
DesignerActionItemCollection items = new DesignerActionItemCollection();
//Define static section header entries.
items.Add(new DesignerActionHeaderItem("Appearance"));
items.Add(new DesignerActionPropertyItem("BackColor",
"Back Color", "Appearance",
"Selects the background color."));
items.Add(new DesignerActionPropertyItem("ForeColor",
"Fore Color", "Appearance",
"Selects the foreground color."));
items.Add(new DesignerActionPropertyItem("LabelText",
"Label Text", "Appearance",
"Type few characters to filter Cities."));
return items;
}
步骤 10:构建项目。
步骤 11:打开 Form1
设计器,将工具箱中的用户控件“MyControl
”拖到设计器表面,然后查看智能标记是否正常工作。
注意
本文示例应用程序中解释的用于创建带智能标记的用户控件的完整代码可与本文一起下载。您可以将 MyControl.cs 文件添加到任何 Windows Forms 应用程序,并在构建项目之前向 System.Design
程序集添加引用。将用户控件放置在任何窗体上,即可体验智能标记功能。

结论
智能标记是菜单式用户界面 (UI) 元素,可提供常用的设计时选项。.NET Framework 提供的许多标准组件和控件都包含智能标记和设计器动词增强功能。本文向您展示了如何为用户控件添加智能标记支持,以便它们可以在 Windows Forms 应用程序中得到充分利用。
历史
- 2009年6月9日:初次发布
- 2009年6月22日:添加了源代码