关于c#:ASP.NET自定义控件-复合

关于c#:ASP.NET自定义控件-复合

ASP.NET Custom Controls - Composites

概要

大家好,
好的,通过自定义控件进一步探索我的冒险...

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

  • UserControls-从UserControl继承并包含在ASCX文件中。它们的功能相当有限,但是在设计人员的支持下,这是获得某些UI通用性的一种快速简便的方法。
  • 自定义复合控件-这些控件从WebControl继承,您可以在其中向CreateChildControls方法内的控件添加预先存在的控件。这提供了很大的灵活性,但是缺少设计人员的支持而没有其他编码。由于它们可以编译成DLL,因此它们具有很高的可移植性。
  • 自定义渲染控件-与自定义复合控件类似,它们被添加到Web控件库项目中。控件的呈现完全由程序员通过重写Render方法来控制。
  • 我的想法..

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

    • 您几乎无法控制HTML输出,因此很难"调试"。
    • CreateChildControls(和后续方法)可以随处忙于Controls.Add(myControl)。
    • 我发现渲染表(用于布局或内容)相当尴尬。

    问题。

    因此,我承认,我对此并不陌生,因此我可能会因为上文提到的一些观点而偏离基础。

    • 您是否使用复合材料?
    • 您有任何巧妙的技巧来控制HTML输出吗?
    • 您是否只是说"让它死了"然后继续创建自定义呈现控件?

    因为我知道良好的控件开发可以节省多少总体开发时间,所以我很想让自己牢牢记住这一点。

    期待您的回答^ _ ^


    我说继续使用自定义呈现控件。我发现,在大多数情况下,合成可以更轻松地完成并在UserControl中使用,但是除此之外,您还需要具有更好的控制度(无双关),才能拥有自己的渲染策略。

    也许控件很简单,值得组合(例如,一个文本框与一个基于javascript / dhtml的datepicker结合使用),但是除了那一个示例之外,自定义呈现的控件似乎是必经之路。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     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()方法中呈现自定义合成,请编写以下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    protected override void RenderContents(HtmlTextWriter o)
    {
        o.WriteControls
             (@"<table>
                   <tr>
                        <td>{0}</td>
                        <td>{1}</td>
                   </tr>
                 </table>"

                ,Text
                ,control1);
     }


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


    在您拥有大型Web应用程序并且想要在许多地方重用大块的情况下,使用自定义复合控件很重要。然后,您将只添加您正在开发的控件的子控件,而无需重复自己。
    在最近的一个大型项目中,我们所做的工作如下:

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

    实际上,您需要一个基类,该基类将负责使用指定的模板初始化容器,并且在模板中找不到控件时也会引发异常。当然,在小型应用程序中这可能是过大的选择。如果您没有重用代码和标记,而只想编写简单的控件,那么最好使用用户控件。


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

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

    为了快速而肮脏的渲染,我使用如下代码:

    1
    2
    3
    4
    5
    6
    writer.Render(@"<table>
                       <tr><td>{0}</td></tr>
                       <tr>
                           <td>"
    , Text);
    control1.RenderControl(writer);
    writer.Render("</td></tr></table>");

    为了初始化控件属性,我使用属性初始化程序语法:

    1
    2
    3
    4
    childControl = new Control {  ID="Foo"
                                , CssClass="class1"
                                , CausesValidation=true;
                               };

    您可能可以利用此技术来简化设计时间:

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

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

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


    推荐阅读