65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.43/5 (14投票s)

2005年3月22日

2分钟阅读

viewsIcon

164219

downloadIcon

1806

一篇关于在 ASP.NET 中创建自定义用户控件设计器的文章。

User Control Designer in Action

引言

用户控件是一种服务器控件,可以使用声明性样式作为 ASP.NET 网页来编写。它们为 Web 开发人员提供了一种快速创建服务器控件的方法。

用户控件在 VS.NET 中缺乏最小的设计时支持。它们的属性无法使用属性网格进行编辑。本文旨在为用户控件创建自定义设计器,从而允许使用属性网格编辑其属性。

页眉用户控件

下面的代码显示了一个页眉用户控件,它公开了 HeadingSubHeading 属性,允许用户为页面提供标题和副标题。

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 控件库”项目模板。

如下所示,向项目添加一个组件类

Creating the New Component Class

组件类是继承 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 向用户公开 HeadingSubHeading 属性。用户可以使用属性网格设置这些属性。

将设计器与页眉用户控件关联

打开包含页眉用户控件的项目。将 HeaderDesigner 组件添加到工具箱中的“组件”选项卡,如下所示

Adding HeaderDesigner to Toolbox

HeaderDesigner 拖放到设计图面上。现在,您可以使用属性网格设置 HeadingSubHeading 属性,如下所示

Setting Properties for UserControl

打开页面的代码隐藏文件,并添加以下代码

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。
© . All rights reserved.