NoSpamEmailHyperlink: 4.设计时功能

分享于 

15分钟阅读

Web开发

  繁體 雙語

Transformation from ASP.NET properties to HTML

简介

这是系列六篇文章中第四篇,在设计。开发和实际使用一个功能完备的ASP.NET 自定义控件之后。

全文的完整 List 如下所示:

这些文章不是对自定义控制开发( 有 700页的网页书几乎没有覆盖它)的全面看法,但它们覆盖了很多基本的基础。

目的是在一个完全可以重用和可以自定义的控制( 与许多虚构的例子相反) 上进行这样的操作。

本文讨论使控件正确从 Visual Studio. NET 工具箱中进行操作。自定义设计器中的呈现以及进一步自定义数据绑定控件呈现的技术。 对于那些在编写网页控件但不理解用户提供的功能的用户而言,它是。 NET框架使你的控件在所见即所得设计器中显示为专业的,如 Visual Studio。 网网。

它至少具备 C#。WebControl -derived类和. NET 框架属性的基本知识。

从系列的第一篇文章中可以下载到。

添加设计器功能

WebConrtol 开发中,文档化的最少方面之一是如何在所见即所得的设计器中使控件成为"看看"。

If limit .Text 属性,则控件将显示在属性( 因为设计器不支持 JavaScript ) 中,如果未填充任何属性,则在属性中显示为小框,并且可能根本不显示任何属性。

这对于web页开发人员来说没有什么好消息,所以很重要的是包含一个小的设计器功能。

工具箱操作指南

除非通知设计器控件标记应该如何,否则自定义控件将不能正常运行。

[//...
ToolboxData("<{0}:NoSpamEmailHyperlink runat="server"></{0}:NoSpamEmailHyperlink>"),
//...]publicclass NoSpamEmailHyperlink : System.Web.UI.WebControls.WebControl
{//.. .}

ToolboxDataAttribute 使用字符串格式化来创建在页面中放置的完整标记或者父控件。

默认情况下,{0} marker 替换为"cc1"。 可以使用 TagPrefixAttribute 自定义这里前缀。

[assembly: TagPrefix("CP.WebControls", "cpspam")]

这个属性可以定义在项目中的任何位置,但是作为程序集的范围,在 AssemblyInfo.cs. 中定义它更有意义。

除了向页添加相关标记外,设计器还将检查程序集是否已经使用以下代码行在页中使用"已经注册":

<%@RegisterTagPrefix="cpspam"Namespace="CP.WebControls"Assembly="CP.WebControls.NoSpamEmailHyperlink"%>

如果已经使用其他 TagPrefix 注册了相同的程序集,则忽略 TagPrefixAttribute,并使用注册的前缀来生成标记。

如果已经使用相同的TagPrefix 注册了另一个程序集,则将数字添加到这里程序集的进一步实例中。

如果程序集或者 TagPrefix 都未注册,则 <%@ register。%> 由设计器添加行。

自定义工具箱 icon

NoSpamEmailHyperlink 中还包含一个定制的icon。 这很容易做到,并向控件添加一个样式元素。

只需创建一个 16位 x16. bmp 位图与你的控制( 在这种情况下,nospamemailhyperlink.bmp ) 相同的基文件名。 为你希望透明的像素使用明亮的绿色( RGB = 00 FF00 ),并绘制一个 icon。

Visual Studio. NET 用户可以在解决方案资源管理器中选择文件,将"生成操作"属性更改为"嵌入式资源"。 使用其他ide的开发人员应该查阅他们的文档来了解如何执行这里操作。

Control appears different in browser than it did in the designer

注意位图将假定项目的默认名称空间,这应该是你的控件类的名称空间,否则你必须使用将控件指向它的icon。

个人免责声明:我容易承认我不适合设计- 这是一个信封,最好在 16个空间。 如果谁有更好的icon,我将乐意考虑替换它。

自定义ControlDesigner类

WebControl 类附加到一个 ControlDesigner 类,该类处理控件在设计时出现的方式。 它本质上使用控件方法的.Render() 来生成一些 HTML。 如果长度为零,则生成一些标准的HTML以使控件可见。

在许多情况下这已经足够了,但是定制 ControlDesigner 类有两个通用。

  • 重写 GetDesignHtml() 以模拟设计器未处理的某些 JavaScript。
  • 重写 GetEmptyDesignHtml() 以在 .Render() 返回的HTML返回时创建自定义 marker。
publicclass NoSpamEmailHyperlinkDesigner : ControlDesigner
{//.. .}

我们通知控件它有一个使用 ControlDesignerAttribute的定制设计器。

[//...
ControlDesigner(typeof(NoSpamEmailHyperlinkDesigner)),
//...]publicclass NoSpamEmailHyperlink : System.Web.UI.WebControls.WebControl
{//.. .}

Control appears different in browser than it did in the designer

对于 NoSpamEmailHyperlink,我们不希望在设计器中加密电子邮件地址时,它不会出现在运行时( 请参见上方)。 因此我们需要一个 NoSpamEmailHyperlinkDesigner 类来模拟 JavaScript。

自定义设计器的所有实现都应重写 .Initialize() 方法,以引发 ControlDesigner 与它的所用的控件类型的异常。

publicoverridevoid Initialize(System.ComponentModel.IComponent component)
{
 // Throw an exception if the designer is attached// to a control for which it is not intendedif (! (component is NoSpamEmailHyperlink))
 {
 thrownew InvalidOperationException(
 this.GetType().FullName 
 + " only supports controls derived" + " from CP.WebControls.NoSpamEmailHyperlink" );
 }
 base.Initialize (component);
}

这允许任何重载方法对它处理的控件类型作出某些假设,如下面的代码所示。

不解析 base.GetDesignTimeHtml() 返回的HTML并解码电子邮件地址,我们可以在呈现时设置控制属性的.EncodeInText

每次呈现控件时,它都比编码和解码更有效,而且每次使用控件都是不可以见的。 只要在呈现后将控件返回到初始状态,页面设计器将永远不会看到更改。

实际上,对于 .GetDesignTimeHtml()的任何自定义实现来说,这是一个推荐的设计策略:

  • 更改控件的属性。
  • 调用基实现。
  • 如果发生任何错误,请使用异常生成错误标记。
  • 将控件返回到它的初始状态。
  • 如果没有要返回的HTML,则获取空控件 marker。
publicoverridestring GetDesignTimeHtml()
{
 // Initialize NoSpamEmailHyperlink nseh = (NoSpamEmailHyperlink)Component;
 bool storeEncodeInText = nseh.EncodeInText;
 string rtn = null;
 try {
 // Do not encode the Text property// because JavaScript will not be run in designer nseh.EncodeInText = false;
 rtn = base.GetDesignTimeHtml();
 }
 catch (Exception ex)
 {
 // If something fails, report as usual rtn = GetErrorDesignTimeHtml(ex);
 }
 finally {
 // Always reset the control's flag to initial state nseh.EncodeInText = storeEncodeInText;
 }
 // If we have nothing to display, go with// the default"Empty" Htmlif (rtn == null || rtn.Length == 0)
 rtn = GetEmptyDesignTimeHtml();
 return rtn;
}

唯一的问题是控件方法的.Render() 将返回打开和关闭的标记( <> </> ),即使 .Text 或者 .Email 属性中没有任何内容。 因此控件将显示为设计器中的一个小空框,这并不十分容易选择。

这里问题可以通过重写控制方法的.Render() 来绕过。

protectedoverridevoid Render(HtmlTextWriter output)
{
 // If we don't have anything to display don't even render// the start and end blocks. This assures that the page shows// nothing but the VS.NET designer has a selectable labelif (Email.Length == 0 && Text.Length == 0 && Controls.Count == 0)
 return;
 base.Render(output);
}

现在,页面设计器中通常会像对最终用户那样显示非数据绑定 NoSpamEmailHyperlink 控件。 如果在浏览器中不可以见,它仍然显示在页面设计器中,但是使用标准显示字符串。

自定义DataBindingHandler类

WebControl 被重新绑定时,在设计模式下,绑定属性被认为是空白的。 其中一个例外是 innertext 属性,其中内容仅部分数据绑定。 这种情况下,在绑定区域之外的任何文本都被使用,其他任何文本都被认为是空白的。

例如可以将以下控件定义包含在 DataGrid 中:

<cpspam:NoSpamEmailHyperlinkid="nseh"runat="server"Email='<%# DataBinder.Eval(Container.DataItem, "Email") %>'ScrambleSeed='<%# DataBinder.Eval(Container.DataItem, "ID") %>'><%# DataBinder.Eval(Container.DataItem, "Name") %> (<%# DataBinder.Eval(Container.DataItem, "Email") %>)</cpspam:NoSpamEmailHyperlink>

在 Visual Studio. NET 设计器中,.Email.ScrambleSeed 属性被视为 .Text 内部属性被认为是") 时,。

The control does not appear to be a hyperlink in the designer, nor does it contain any logical representation of the text

在它的他可以见的控件( 如 TextBox 或者 DropDownList ) 中,这并不重要。 我们不需要看到文本,以了解控件在那里。

但在文本控件中,如 Label 或者 NoSpamEmailHyperlink,我们需要将一些文本放入属性中,否则控件将在设计器中不可见。

这是通过实现 DataBindingHandler 类实现的,重写 .DataBindControl() 方法并通过 DataBindingHandlerAttribute 通知我们的新设计时责任。

[//...
DataBindingHandler(typeof(NoSpamEmailHyperlinkDataBindingHandler)),
//...]publicclass NoSpamEmailHyperlink : System.Web.UI.WebControls.WebControl
{//.. .}

Label 控件实现 TextDataBindingHandler,它只使用字符串"数据绑定"填充标签的.Text 属性。

然后,控件作为一段文本出现在设计器中: Databound数据绑定""

对于 NoSpamEmailHyperlink,我们希望控件在设计器中显示为超链接。 因此,我们必须在 DataBindingHandler 类中同时填充 .Text.Email 属性。

publicclass NoSpamEmailHyperlinkDataBindingHandler : DataBindingHandler
{
 publicoverridevoid DataBindControl(
 System.ComponentModel.Design.IDesignerHost designerHost,
 System.Web.UI.Control control
 )
 {
 NoSpamEmailHyperlink nseh = control as NoSpamEmailHyperlink;
 if (nseh!= null)
 {
 // Set the text and email properties, so that the// control looks like a hyperlink in a datalist/grid nseh.Text = "Databound";
 nseh.Email = "Databound@Databound.com";
 }
 }
}

它完全没有什么实际的区别,用来填充 .Email 属性。 内容将永远不会被看到。 唯一的规则是它不能为零长度,因为如果它是 href 标记的属性未填充,并且控件在设计器中显示为纯文本。

结论

本文中详细介绍的大多数技术都非常容易实现并向控件中添加一些不能量化的质量元素。

应该为任何自定义控件实现 ToolboxDataAttribute 和 icon。 只要用户在渲染后更改外观,或者任何缺省的"空白"设计时间HTML都不足以,只需要一个自定义 ControlDesigner 类。 无论在设计时,如果控件可以能出现不可以见或者不正确,则必须使用自定义 DataBindingHandler

现在检查了 NoSpamEmailHyperlink 所需的完整代码,然后考虑一些示例,看看如何定制 NoSpamEmailHyperlink 以进一步混淆控制功能。


DES  时间  FUNC  函数  设计  functional  
相关文章