带有设计时支持的ExpandingTable

分享于 

12分钟阅读

Web开发

  繁體

介绍

这个项目开始得很简单,构建一个可折叠的网页控件来显示内容。 一路上,我不断扩展它,学习如何在 Visual Studio. NET IDE中构建和控制web控件。 在表单的HTML视图中,我最好奇的是添加设计时支持,而不仅仅是属性。 虽然控件仍然有一些缺点,但我相信它是它的他人的一个好学习工具。

概述

控件本身非常简单,table 包含两行,一个用于 header 显示,另一个用于内容。 header 有两个列,一个用于 icon 指示折叠或者展开状态,另一个用于表示图像或者文本。

展开

Sample screenshot

折叠

Sample screenshot

生成控件

实际上,创建这个控件没有什么特殊之处。 我们可以看到,它是从 System.Web.UI.WebControls 派生的,也是 INamingContainer

publicclass ExpandingDiv : WebControl, INamingContainer

通过重写 CreateChildControls() 方法,我们可以根据需要呈现控件。 自定义控件生成的示例有很多。 我不会太详细的。

protectedoverridevoid CreateChildControls()
{
 // Needed to have the icons specified firstif( m_strExpandedIcon == string.Empty 
 || m_strCollaspedIcon == string.Empty )
 thrownew Exception("Expanded and collapsed icon must be defined");
 // Start with a clean slate Controls.Clear(); 
 // Create the table that will house everything Table table = new Table();
 table.Attributes.Add("border", Border.ToString());
 table.Attributes.Add("CellPadding", 
 CellPadding.ToString());
 table.Attributes.Add("CellSpacing", 
 CellSpacing.ToString());
 table.Width = Width;
 // Add to the controls collection now so// a UniqueID is generated Controls.Add(table); 
 // Create the header row and add it to the table TableRow rowHeader = CreateHeaderRow();
 table.Rows.Add(rowHeader); 
 // If a template has been definedif( m_ItemTemplate!= null )
 {
 CreateTemplateRow(ref table); 
 string strParams = string.Format("Expand('{0}_{1}', 
 '{0}_{2}')", UniqueID, CONTENT_ID, ICON_ID);
 rowHeader.Cells[0].Attributes.Add("OnClick", strParams);
 rowHeader.Cells[0].Attributes.Add("OnMouseOver", 
 "this.style.cursor='pointer'") ;
 }
 // Register the script for client-side event RegisterScript();
}

项模板

控件 below 中显示的内容 header 是使用 ItemTemplate 控制的。 为了提供最大的灵活性,这里模板中的任何内容都将按原样呈现到表中。

<ItemTemplate><fontsize="4">Content will go here</font></ItemTemplate>
privatevoid CreateTemplateRow(ref Table table)
{
 ExpandingDivItem item = new ExpandingDivItem();
 m_ItemTemplate.InstantiateIn(item.Cells[0]);
 item.ID = CONTENT_ID;
 table.Rows.Add(item);
}

设计器支持

要使控件显示为web窗体设计器中除灰色 block 之外的其他内容,我们必须创建一个从 System.Web.UI.Design.ControlDesigner 并将它的与我们要显示的类关联起来。

publicsealedclass ExpandingDivDesigner : ControlDesigner

通过添加 DesignerAttribute,设计器与类关联。

[DesignerAttribute(typeof(ExpandingDivDesigner), 
 typeof(IDesigner))]publicclass ExpandingDiv : WebControl, INamingContainer

尽管 ControlDesigner 类有几个方法和属性,但是我们只对这个例子感兴趣,GetDesignTimeHtml()GetErrorDesignTimeHtml()

在设计模式下,重写 GetDesignTimeHtml() 以控制控件在网页窗体上的呈现方式。 就像你可以通过 NAME 猜测的,需要返回的是标准的HTML标记。 这里,我使用 StringBuilder 来捕获标记和属性,并返回它们。 ControlDesigner 类的Component 属性使我们能够访问我们设计的控件的属性,并将它的投入正确的类 ((ExpandingDiv)Component)

publicoverridestring GetDesignTimeHtml()
{
 try {
 System.Text.StringBuilder sb = new 
 System.Text.StringBuilder(); 
 sb.AppendFormat("<table border={0} cellpadding={1} 
 cellspacing={2} width={3}>", 
 ((ExpandingDiv)Component).Border, 
 ((ExpandingDiv)Component).CellPadding, 
 ((ExpandingDiv)Component).CellSpacing, 
 ((ExpandingDiv)Component).Width); 
 if( ((ExpandingDiv)Component).HeaderBackgroundColor!= 
 System.Drawing.Color.Empty )
 sb.AppendFormat("<tr bgcolor={0} class={1}>", 
 System.Drawing.ColorTranslator.ToHtml(((ExpandingDiv)
 Component).HeaderBackgroundColor), 
 ((ExpandingDiv)Component).HeaderCssClass);
 else sb.Append("<tr>");
 if(((ExpandingDiv)Component).ExpandedIcon == string.Empty )
 thrownew Exception("Expanded Icon not defined");
 sb.AppendFormat("<td align={1} width=1><img src='{0}'></td>", 
 ((ExpandingDiv)Component).ExpandedIcon, 
 ((ExpandingDiv)Component).HeaderAlignment);
 if(((ExpandingDiv)Component).HeaderImage!= null )
 sb.AppendFormat("<td><img src='{0}'></td>", 
 ((ExpandingDiv)Component).HeaderImage);
 elseif(((ExpandingDiv)Component).HeaderText!= 
 string.Empty )
 sb.AppendFormat("<td>{0}</td>", 
 ((ExpandingDiv)Component).HeaderText ); 
 sb.Append("</tr>"); 
 if( ((ExpandingDiv)Component).ItemTemplate!= null )
 {
 Literal literal = new Literal();
 ((ExpandingDiv)Component).ItemTemplate.InstantiateIn(literal);
 sb.AppendFormat("<tr><td colspan=2>{0}</td></tr>", 
 literal.Text);
 }
 sb.Append("</table>"); 
 return sb.ToString(); 
 }
 catch(Exception ex)
 {
 return GetErrorDesignTimeHtml(ex);
 }
}

如果在设计器中呈现控件期间发生任何异常,则通过重写你猜到的GetErrorDesignTimeHtml 来处理它们。 在这种情况下,我们只返回一个描述异常的简单字符串。 也可以重写 CreatePlaceHolderDesignTimeHtml() 以提供自定义呈现。

protectedoverridestring GetErrorDesignTimeHtml(Exception e)
{
 return CreatePlaceHolderDesignTimeHtml(e.Message);
}

设计时间 HTML

只要我们使用属性窗口改变控件的外观,到目前为止,一切都是很好的。 但是当我们使用HTML视图时会发生什么? 使用标准控件,如 asp:label 或者 asp:button,在控件的开始标记中打开空格键时,可以获得可以用属性的列表。

Sample screenshot

如果键入不受控件支持的属性,它会显示一个红色的下划线,通知你方法的错误。 问题是,编辑器如何知道你的控件可以能不支持或者可以能不支持的属性。

答案是,在你告诉它之前。

控制模式

控件的支持属性( 自定义或者预包装) 通过使用模式文件来控制。 looking [VS.NET]Common7Packagesschemasxml, 文件,你会看到文件 asp.xsd. 这个文件包含所有的定义,在 ASP.NET 控件的控件中附带的。

<!-- <asp:Image> --><xsd:complexTypename="ImageDef"vs:noambientcontentmodel="true"><xsd:attributename="AlternateText"type="xsd:string"/><xsd:attributename="Enabled"type="xsd:boolean"vs:readonly="true"/><xsd:attributename="ImageAlign"type="ImageAlign"/><xsd:attributename="ImageUrl"type="xsd:anyURI"/><xsd:attributename="BorderWidth"type="ui4"/><xsd:attributename="BorderColor"type="xsd:string"vs:builder="color"/><xsd:attributename="BorderStyle"type="BorderStyle"/><xsd:attributeGroupref="WebControlAttributes"/></xsd:complexType>

若要使控件在HTML设计器中有用,必须创建类似的架构文件并将它的放置在同一文件夹中。 注意,必须包括要支持的每个属性,包括ID和 RunAt 属性。有关架构注释的详细信息,请参见这里的

<xsd:complexTypename="ExpandingDivDef"vs:noambientcontentmodel="true"><xsd:choice><xsd:elementname="ItemTemplate"type="TemplateDef"form="unqualified"vs:blockformatted="true"/></xsd:choice><xsd:attributename="ID"type="xsd:string"/><xsd:attributename="Runat"><xsd:simpleType><xsd:restrictionbase="xsd:string"><xsd:enumerationvalue="server"/></xsd:restriction></xsd:simpleType></xsd:attribute><xsd:attributename="HeaderBackgroundColor"type="xsd:string"vs:builder="color"/><xsd:attributename="HeaderImage"type="xsd:anyURI"/><xsd:attributename="HeaderText"type="xsd:string"/><xsd:attributename="HeaderAlignment"type="HorizontalAlign"/><xsd:attributename="HeaderCssClass"type="xsd:string"/><xsd:attributename="CollapsedIcon"type="xsd:anyURI"/><xsd:attributename="ExpandedIcon"type="xsd:anyURI"/><xsd:attributename="Border"type="xsd:ui4"/><xsd:attributename="CellSpacing"type="xsd:ui4"/><xsd:attributename="CellPadding"type="xsd:ui4"/><xsd:attributename="Width"type="xsd:string"/><xsd:attributename="EnableViewState"type="xsd:boolean"/><xsd:attributeGroupref="Header"/></xsd:complexType>

还需要一步来完成HTML设计器支持。 虽然架构文件存在,但必须添加 xmlns 属性到主体标记,控件属性的属性将在编辑器中被识别。

<bodyMS_POSITIONING="GridLayout"xmlns:MANSoftControls="urn:http://www.teoulmoon.com/mansoft/schemas">

我还没有找到如何使这个步骤成为自动步骤,因这里现在必须手动完成。

结束语

如前所述,控件本身非常简单;重点是添加设计时支持。 我没有讨论过几个领域,但这篇文章应该足以为那些想要添加自定义控件的开始点。


EXP  SUP  DES  时间  设计  Expand