C# ASP.NET 自定义控件 - 组合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17532/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-01 08:58:50  来源:igfitidea点击:

ASP.NET Custom Controls - Composites

提问by Rob Cooper

Summary

概括

Hi All,
OK, further into my adventures with custom controls...

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

In summary, here is that I have learned of three main "classes" of custom controls. Please feel free to correct me if any of this is wrong!

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

  1. UserControls- Which inherit from UserControland are contained within an ASCXfile. These are pretty limited in what they can do, but are a quick and light way to get some UI commonality with designer support.
  2. Custom Composite Controls- These are controls that inherit from WebControlwhere you add pre-existing controls to the control within the CreateChildControlsmethod. This provides great flexibility, but lack of designer support without additional coding. They are highly portable though since they can be compiled into a DLL.
  3. Custom Rendered Controls- Similar to Custom Composite Controls, these are added to a Web Control Library project. The rendering of the control is completely controlled by the programmer by overriding the Rendermethod.
  1. UserControls- 从UserControl继承并包含在ASCX文件中。它们的功能非常有限,但可以通过设计人员的支持快速轻松地获得一些 UI 通用性。
  2. 自定义复合控件- 这些是从WebControl继承的控件,您可以在其中向CreateChildControls方法中的控件添加预先存在的控件。这提供了极大的灵活性,但缺乏设计人员的支持而无需额外编码。它们具有高度的可移植性,因为它们可以编译成 DLL。
  3. 自定义渲染控件- 与自定义复合控件类似,它们被添加到 Web 控件库项目中。控件的渲染完全由程序员通过重写Render方法来控制。

My Thoughts..

我的想法..

OK, so while playing with custom composites, I found the following:

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

  • You have little/no control over the HTML output making it difficult to "debug".
  • The CreateChildControls(and subsequent methods) can get real busy with Controls.Add(myControl)everywhere.
  • I found rendering tables (be it for layout or content) to be considerably awkward.
  • 您几乎/无法控制 HTML 输出,因此很难“调试”。
  • 的CreateChildControls(以及随后的方法)可以得到真正的忙Controls.Add被(myControl)无处不在。
  • 我发现渲染表(无论是用于布局还是用于内容)非常笨拙。

The Question(s)..

问题..

So, I admit, I am new to this so I could be way off-base with some of my points noted above..

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

  • Do you use Composites?
  • Do you have any neat tricks to control the HTML output?
  • Do you just say "to hell with it" and go ahead and create a custom rendered control?
  • 你使用复合材料吗?
  • 你有什么巧妙的技巧来控制 HTML 输出吗?
  • 你只是说“见鬼去吧”然后继续创建一个自定义呈现的控件?

Its something I am keen to get really firm in my mind since I know how much goodcontrol development can cut overall development time.

因为我知道好的控制开发可以缩短整体开发时间,所以我很想把它牢记在心。

I look forward to your answers ^_^

期待你的回答^_^

采纳答案by Jon Limjap

I say go ahead with the custom rendered control. I find that in most cases the composite can be easier done and used in a UserControl, but anything beyond that and you'd need to have a finer degree of control (pun unintended) to merit your own rendering strategy.

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

There maybe controls that are simple enough to merit a composite (e.g., a textbox combined with a javascript/dhtml based datepicker, for example) but beyond that one example, it looks like custom rendered controls are the way to go.

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

回答by Mark Cidade

I often use composite controls. Instead of overriding Render or RenderContents, just assign each Control a CssClass and use stylesheets. For multiple Controls.Add, I use an extension method:

我经常使用复合控件。无需覆盖 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);
 }

For quick and dirty rendering, I use something like this:

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

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

For initializing control properties, I use property initializer syntax:

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

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

回答by Slavo

Using custom composite controls has a point in a situation where you have a large web application and want to reuse large chunks in many places. Then you would only add child controls of the ones you are developing instead of repeating yourself. On a large project I've worked recently what we did is the following:

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

  • Every composite control has a container. Used as a wrapped for everything inside the control.
  • Every composite control has a template. An ascx file (without the <%Control%> directive) which only contains the markup for the template.
  • The container (being a control in itself) is initialized from the template.
  • The container exposes properties for all other controls in the template.
  • You only use this.Controls.Add([the_container]) in your composite control.
  • 每个复合控件都有一个容器。用作控件内所有内容的包装。
  • 每个复合控件都有一个模板。一个仅包含模板标记的 ascx 文件(没有 <%Control%> 指令)。
  • 容器(本身就是一个控件)是从模板初始化的。
  • 容器公开模板中所有其他控件的属性。
  • 您只能在复合控件中使用 this.Controls.Add([the_container]) 。

In fact you need a base class that would take care of initializing a container with the specified template and also throw exceptions when a control is not found in the template. Of course this is likely to be an overkill in a small application. If you don't have reused code and markup and only want to write simple controls, you're better off using User Controls.

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

回答by Mark Cidade

Here's another extension method that I use for custom rendering:

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

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

Then, to render a custom composite in the RenderContents() method I write this:

然后,为了在 RenderContents() 方法中呈现自定义组合,我这样写:

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

回答by Slavo

Rob, you are right. The approach I mentioned is kind of a hybrid. The advantage of having ascx files around is that on every project I've seen, designers would feel most comfortable with editing actual markup and with the ascx you and a designer can work separately. If you don't plan on actual CSS/markup/design changes on the controls themselves later, you can go with a custom rendered control. As I said, my approach is only relevant for more complicated scenarios (and these are probably where you need a designer :))

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

回答by Andrew Myhre

You might be able to make use of this technique to make design-time easier:

您也许可以利用此技术使设计时更轻松:

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

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

Basically you create an instance of a user control at runtime using the LoadControl method, then hand it a statebag of some kind, then attach it to the control tree. So your composite control would actually function like more of a controller, and the .ascx file would be like a view.

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

This would save you the trouble of having to instantiate the entire control tree and style the control in C#!

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