在 ASP.NET 中创建自定义用户控件设计器






4.43/5 (14投票s)
2005年3月22日
2分钟阅读

164219

1806
一篇关于在 ASP.NET 中创建自定义用户控件设计器的文章。
引言
用户控件是一种服务器控件,可以使用声明性样式作为 ASP.NET 网页来编写。它们为 Web 开发人员提供了一种快速创建服务器控件的方法。
用户控件在 VS.NET 中缺乏最小的设计时支持。它们的属性无法使用属性网格进行编辑。本文旨在为用户控件创建自定义设计器,从而允许使用属性网格编辑其属性。
页眉用户控件
下面的代码显示了一个页眉用户控件,它公开了 Heading
和 SubHeading
属性,允许用户为页面提供标题和副标题。
VB.NET
<%@ Control Language="vb" AutoEventWireup="false"
Codebehind= "Header.ascx.vb" Inherits="CustomDesignersWebVB.Header" %>
<table align="center" ID= "tblHeader">
<tr>
<td><asp:label id="lblHeading" Font-Size="18" Font-Name="Arial"
Font-Bold="True" Runat="server">Heading</asp:label></td>
</tr>
<tr>
<td><asp:label id="lblSubHeading" Font-Size="14" Font-Name="Arial"
Font-Bold="True" Runat="server">Sub Heading</asp:label></td>
</tr>
</table>
Public Property Heading() As String
Get
Return lblHeading.Text
End Get
Set(ByVal Value As String)
lblHeading.Text = Value
End Set
End Property
Public Property SubHeading() As String
Get
Return lblSubHeading.Text
End Get
Set(ByVal Value As String)
lblSubHeading.Text = Value
End Set
End Property
C#
<%@ Control Language="C#" AutoEventWireup="false"
Codebehind= "Header.ascx.cs" Inherits="CustomDesignersWebCS.Header" %>
<table align="center" ID= "tblHeader">
<tr>
<td><asp:label id="lblHeading" Font-Size="18" Font-Name="Arial"
Font-Bold="True" Runat="server">Heading</asp:label></td>
</tr>
<tr>
<td><asp:label id="lblSubHeading" Font-Size="14" Font-Name="Arial"
Font-Bold="True" Runat="server">Sub Heading</asp:label></td>
</tr>
</table>
public string Heading
{
get
{
return lblHeading.Text;
}
set
{
lblHeading.Text=value;
}
}
public string SubHeading
{
get
{
return lblSubHeading.Text;
}
set
{
lblSubHeading.Text=value;
}
}
为页眉用户控件创建自定义设计器
启动 Visual Studio .NET,使用“文件 | 新建 | 项目”菜单项,然后选择“Web 控件库”项目模板。
如下所示,向项目添加一个组件类
组件类是继承 System.Component.Component
的类。它可以添加到 VS.NET 的工具箱中,并且可以拖放到设计图面上,选择后,其属性将使用属性网格显示。
以下是 HeaderDesigner
组件类的代码列表
C#
private string _Heading ;
private string _SubHeading;
public string Heading
{
get
{
return _Heading;
}
set
{
_Heading=value;
}
}
public string SubHeading
{
get
{
return _SubHeading;
}
set
{
_SubHeading=value;
}
}
VB.NET
Private _Heading As String
Private _SubHeading As String
Public Property Heading() As String
Get
Return _Heading
End Get
Set(ByVal Value As String)
_Heading = Value
End Set
End Property
Public Property SubHeading() As String
Get
Return _SubHeading
End Get
Set(ByVal Value As String)
_SubHeading = Value
End Set
End Property
Header Designer 向用户公开 Heading
和 SubHeading
属性。用户可以使用属性网格设置这些属性。
将设计器与页眉用户控件关联
打开包含页眉用户控件的项目。将 HeaderDesigner
组件添加到工具箱中的“组件”选项卡,如下所示
将 HeaderDesigner
拖放到设计图面上。现在,您可以使用属性网格设置 Heading
和 SubHeading
属性,如下所示
打开页面的代码隐藏文件,并添加以下代码
C#
protected Header Header1;
private void Page_Load(object sender, System.EventArgs e)
{
//Glue code to associate the Usercontrol with the Designer
if(!IsPostBack)
{
CustomDesignersCS.DesignerHelper.BindDesignerToControl(headerDesigner1,
Header1);
}
}
VB.NET
Protected Header1 As Header
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
If Not Page.IsPostBack Then
CustomDesignersVB.DesignerHelper.BindDesignerToControl(HeaderDesigner1, _
Header1)
End If
End Sub
BindDesignerToControl
函数是将 HeaderDesigner
属性绑定到用户控件属性的粘合代码。它使用反射来读取设计器属性,并将它们与页眉用户控件中的相应属性相关联。
C#
public class DesignerHelper
{
public static void
BindDesignerToControl(System.ComponentModel.Component designer, Control ctl)
{
BindDesignerToObject(designer, ctl);
}
public static void
BindDesignerToObject(System.ComponentModel.Component designer, Object obj)
{
//Get object properties using Reflection
PropertyDescriptorCollection colWebCtlPropDesc =
TypeDescriptor.GetProperties(obj);
//Get Designer properties using Reflection
PropertyDescriptorCollection coldesignerPropDesc =
TypeDescriptor.GetProperties(designer);
//Loop through all Designer properties
//Each designer property corresponds to webcontrol property
foreach(PropertyDescriptor pd in coldesignerPropDesc)
{
PropertyDescriptor webctlpd = colWebCtlPropDesc.Find(pd.Name, true);
if (webctlpd!=null)
{
//Assign the designer property value to web control's property
webctlpd.SetValue(obj, pd.GetValue(designer));
}
}
}
}
VB.NET
Public NotInheritable Class DesignerHelper _
Public Shared Sub BindDesignerToControl(ByVal designer As _
System.ComponentModel.Component, ByRef ctl As Control)
BindDesignerToObject(designer, ctl)
End Sub
Public Shared Sub BindDesignerToObject(ByVal designer As _
System.ComponentModel.Component, ByRef obj As Object)
'Get object properties using Reflection
Dim colWebCtlPropDesc As PropertyDescriptorCollection = _
TypeDescriptor.GetProperties(obj)
'Get Designer properties using Reflection
Dim coldesignerPropDesc As PropertyDescriptorCollection = _
TypeDescriptor.GetProperties(designer)
'Loop through Designer properties
'Each designer property corresponds to webcontrol property
For Each pd As PropertyDescriptor In coldesignerPropDesc
Dim webctlpd As PropertyDescriptor = _
colWebCtlPropDesc.Find(pd.Name, True)
If Not IsNothing(webctlpd) Then
'Assign the designer property value to web control
webctlpd.SetValue(obj, pd.GetValue(designer))
End If
Next
End Sub
End Class
关注点
在撰写本文时,我发现可以使用 WebForms 设计器中的属性网格来设置 BasePage
类(所有页面都从中派生的自定义页面类)的属性。
未来的增强功能和反馈
我计划在时间允许的情况下进行以下增强
- 在
UserControlDesigner
中创建一个名为“UserControl
”的新属性,该属性列出Page
中的所有UserControl
。用户可以从下拉列表中选择他想要绑定到设计器的UserControl
。 - 为设计器创建一个自定义
CodeDOMSerializer
,它可以自动生成绑定代码。
请随时通过电子邮件向我发送您的建议和评论。我很乐意根据您的反馈进行改进。
历史
- 05 年 3 月 21 日 - 版本 1。