概括

大家好,
好的,进一步了解我的自定义控件冒险之旅......

综上所述,这里是我了解了自定义控件的三个主要“类”。如果本文有任何错误,请随时纠正我!

  1. 用户控件 - 继承自 用户控制 并包含在一个 ASCX 文件。它们的功能非常有限,但它们是在设计师支持下获得一些 UI 通用性的快速而轻松的方法。
  2. 自定义复合控件 - 这些是继承自的控件 网页控制 您可以将预先存在的控件添加到 创建子控件 方法。这提供了极大的灵活性,但缺乏设计人员支持而无需额外编码。但它们具有高度可移植性,因为它们可以编译成 DLL。
  3. 自定义渲染控件 - 与自定义复合控件类似,它们被添加到 Web 控件库项目中。控件的呈现完全由程序员通过重写来控制 使成为 方法。

我的想法..

好的,在使用自定义复合材料时,我发现了以下内容:

  • 您几乎无法控制 HTML 输出,因此很难“调试”。
  • 创建子控件 (以及后续方法)可能会变得非常忙碌 控件.添加(myControl) 到处。
  • 我发现渲染表格(无论是布局还是内容)相当尴尬。

问题..

所以,我承认,我对此很陌生,所以我上面提到的一些观点可能会大错特错。

  • 您使用复合材料吗?
  • 你有什么巧妙的技巧来控制 HTML 输出吗?
  • 您是否只是说“见鬼去吧”并继续创建自定义呈现的控件?

这是我渴望在脑海中真正坚定的事情,因为我知道有多少 好的 控制开发可以缩短总体开发时间。

期待您的答复^_^

有帮助吗?

解决方案

我说继续使用自定义呈现的控件。我发现在大多数情况下,复合可以更容易地完成并在 UserControl 中使用,但除此之外,您需要有更精细的控制(双关语无意)以获得您自己的渲染策略。

也许有足够简单的控件值得组合(例如,文本框与基于 javascript/dhtml 的日期选择器相结合),但除了这个示例之外,看起来自定义呈现的控件是一种可行的方法。

其他提示

这是我用于自定义渲染的另一种扩展方法:

 public static void WriteControls
        (this HtmlTextWriter o, string format, params object[] args)
 { 
    const string delimiter = "<2E01A260-BD39-47d0-8C5E-0DF814FDF9DC>";
    var controls  = new Dictionary<string,Control>();

    for(int i =0; i < args.Length; ++i)
    { 
       var c = args[i] as Control; 
       if (c==null) continue;
       var guid = Guid.NewGuid().ToString();
       controls[guid] = c;
       args[i] = delimiter+guid+delimiter;
    }

    var _strings = string.Format(format, args)
                         .Split(new string[]{delimiter},
                                StringSplitOptions.None);
    foreach(var s in _strings)
    { 
       if (controls.ContainsKey(s)) 
           controls[s].RenderControl(o);
       else 
           o.Write(s);
    }
}

然后,为了在 RenderContents() 方法中渲染自定义组合,我编写了以下内容:

protected override void RenderContents(HtmlTextWriter o)
{ 
    o.WriteControls
         (@"<table>
               <tr>
                    <td>{0}</td>
                    <td>{1}</td>
               </tr>
             </table>"
            ,Text
            ,control1);
 }

罗布,你是对的。我提到的方法是一种混合方法。使用 ascx 文件的优点是,在我见过的每个项目中,设计人员都会对编辑实际标记感到最舒服,并且使用 ascx,您和设计人员可以单独工作。如果您不打算稍后对控件本身进行实际的 CSS/标记/设计更改,则可以使用自定义呈现的控件。正如我所说,我的方法仅适用于更复杂的场景(这些可能是您需要设计师的地方:))

我经常使用复合控件。无需重写 Render 或 RenderContents,只需为每个 Control 分配一个 CssClass 并使用样式表即可。对于多个 Controls.Add,我使用扩展方法:

//Controls.Add(c1, c2, c3)
static void Add(this ControlCollection coll, params Control[] controls)
 { foreach(Control control in controls) coll.Add(control);
 }

为了快速而肮脏的渲染,我使用这样的东西:

writer.Render(@"<table>
                   <tr><td>{0}</td></tr>
                   <tr>
                       <td>", Text);
control1.RenderControl(writer);
writer.Render("</td></tr></table>");

为了初始化控件属性,我使用属性初始值设定项语法:

childControl = new Control {  ID="Foo"
                            , CssClass="class1"
                            , CausesValidation=true;
                           };

当您拥有大型 Web 应用程序并希望在许多地方重用大块时,使用自定义复合控件是有道理的。然后,您只需添加您正在开发的子控件,而不必重复自己。在我最近工作的一个大型项目中,我们所做的如下:

  • 每个复合控件都有一个容器。用作控件内所有内容的包装。
  • 每个复合控件都有一个模板。一个 ascx 文件(不带 <%Control%> 指令),仅包含模板的标记。
  • 容器(本身就是一个控件)是从模板初始化的。
  • 该容器公开模板中所有其他控件的属性。
  • 您仅在复合控件中使用 this.Controls.Add([the_container]) 。

事实上,您需要一个基类来负责使用指定模板初始化容器,并在模板中找不到控件时引发异常。当然,这对于小型应用程序来说可能有点过分了。如果您没有重用代码和标记并且只想编写简单的控件,那么最好使用用户控件。

您也许可以利用此技术来简化设计时:

http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx

基本上,您可以使用 LoadControl 方法在运行时创建用户控件的实例,然后将其传递给某种状态包,然后将其附加到控件树。因此,您的复合控件实际上更像是一个控制器,而 .ascx 文件就像一个视图。

这将为您省去实例化整个控件树并在 C# 中设置控件样式的麻烦!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top