【问题标题】:ASP.NET Custom Controls - CompositesASP.NET 自定义控件 - 组合
【发布时间】:2010-09-06 06:17:01
【问题描述】:

总结

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

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

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

我的想法..

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

  • 您几乎/无法控制 HTML 输出,因此难以“调试”。
  • CreateChildControls(和后续方法)可能会因Controls.Add(myControl)而变得非常忙碌。
  • 我发现呈现表格(无论是布局还是内容)都非常尴尬。

问题..

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

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

我很想牢记这一点,因为我知道良好的控件开发可以在多大程度上缩短整体开发时间。

期待你的回答^_^

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

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

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

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

            【讨论】:

              【解决方案6】:

              您或许可以利用这种技术来简化设计时:

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

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

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

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-09-23
                • 2011-06-15
                • 2010-09-12
                • 1970-01-01
                • 2011-12-20
                • 2012-06-07
                • 1970-01-01
                相关资源
                最近更新 更多