ASP.NET自定义控件 - 复合材料

时间:2008-08-20 07:49:07

标签: c# .net asp.net user-controls controls

摘要

大家好,
好的,进一步使用自定义控件进行冒险......

总之,这是我已经了解了自定义控件的三个主要“类”。如果有任何错误,请随时纠正我!

  1. UserControls - 继承自 UserControl 并包含在 ASCX 文件中。这些内容在他们能做的事情上非常有限,但是通过设计师支持获得一些UI通用性是一种快速而轻松的方式。
  2. 自定义复合控件 - 这些控件继承自 WebControl ,您可以在 CreateChildControls 方法中向控件添加预先存在的控件。这提供了极大的灵活性,但缺乏设计师支持而无需额外编码。它们是高度可移植的,因为它们可以编译成DLL。
  3. 自定义渲染控件 - 与自定义复合控件类似,这些控件将添加到Web控件库项目中。控制器的渲染完全由程序员通过覆盖 Render 方法来控制。
  4. 我的想法......

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

    • 您很少/无法控制HTML输出,因此难以“调试”。
    • CreateChildControls (以及后续方法)可以在任何地方真正忙于 Controls.Add(myControl)
    • 我发现渲染表(无论是布局还是内容)都非常尴尬。

    问题......

    所以,我承认,我是新手,所以我可能会偏离上面提到的一些观点......

    • 您使用复合材料吗?
    • 您是否有任何巧妙的技巧来控制HTML输出?
    • 您是否只是说“地狱”并继续创建自定义渲染控件?

    因为我知道良好的控件开发能够缩短整体开发时间,所以我很想在脑海里真正坚定。

    我期待你的回答^ _ ^

6 个答案:

答案 0 :(得分:5)

我说继续使用自定义渲染控件。我发现在大多数情况下,复合可以更容易地完成并在UserControl中使用,但除此之外的任何东西都需要有更好的控制程度(双关语),值得你自己的渲染策略。

可能有一些控件非常简单,值得一个复合(例如,一个文本框与基于javascript / dhtml的日期选择器相结合),但除了这个例子之外,它看起来像是自定义渲染控件。< / p>

答案 1 :(得分:3)

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

 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);
 }

答案 2 :(得分:2)

罗布,你是对的。我提到的方法是一种混合方式。拥有ascx文件的优势在于,在我看过的每个项目中,设计师都会觉得编辑实际标记最为舒适,而ascx和设计师可以分开工作。如果您以后不打算对控件本身进行实际的CSS /标记/设计更改,则可以使用自定义呈现控件。正如我所说,我的方法仅适用于更复杂的场景(这些可能是您需要设计师的地方)。)

答案 3 :(得分:1)

我经常使用复合控件。而不是重写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;
                           };

答案 4 :(得分:1)

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

  • 每个复合控件都有一个容器。用作控件内部所有内容的包装。
  • 每个复合控件都有一个模板。一个ascx文件(没有&lt;%Control%&gt;指令),只包含模板的标记。
  • 容器(作为控件本身)从模板初始化。
  • 容器公开模板中所有其他控件的属性。
  • 您只在复合控件中使用this.Controls.Add([the_container])。

实际上,您需要一个基类来处理使用指定模板初始化容器,并在模板中找不到控件时抛出异常。当然,这在小型应用程序中可能是一种过度杀伤力。如果您没有重用代码和标记,并且只想编写简单的控件,那么最好使用用户控件。

答案 5 :(得分:0)

您可以使用这种技术来简化设计时间:

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

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

这样可以省去必须实例化整个控制树并在C#中设置控件样式的麻烦!