Пользовательские элементы управления ASP.NET - Композиты - PullRequest
19 голосов
/ 20 августа 2008

Резюме

Привет всем,
ОК, дальше в мои приключения с пользовательскими элементами управления ...

Итак, вот что я узнал о трех основных "классах" пользовательских элементов управления. Пожалуйста, не стесняйтесь поправлять меня, если что-то из этого не так!

  1. UserControls - которые наследуются от UserControl и содержатся в файле ASCX . Они довольно ограничены в своих возможностях, но это быстрый и легкий способ получить некоторую общность пользовательского интерфейса с поддержкой дизайнеров.
  2. Пользовательские составные элементы управления - это элементы управления, которые наследуются от WebControl , где вы добавляете уже существующие элементы управления в элемент управления в методе CreateChildControls . Это обеспечивает большую гибкость, но отсутствие поддержки дизайнера без дополнительного кодирования. Они очень легко переносимы, поскольку их можно скомпилировать в DLL.
  3. Пользовательские визуализированные элементы управления - Подобно пользовательским составным элементам управления, они добавляются в проект библиотеки веб-элементов управления. Визуализация элемента управления полностью контролируется программистом путем переопределения метода Render .

Мои мысли ..

ОК, так что, играя с пользовательскими композитами, я обнаружил следующее:

  • Вы практически не контролируете вывод HTML, что затрудняет "отладку".
  • CreateChildControls (и последующие методы) могут быть очень заняты с Controls.Add (myControl) везде.
  • Я обнаружил, что таблицы рендеринга (будь то макет или контент) были довольно неловкими.

Вопрос (ы) ..

Итак, я признаю, я новичок в этом, поэтому я могу быть немного не в своей тарелке с некоторыми из моих пунктов, отмеченных выше ..

  • Вы используете композиты?
  • Есть ли у вас какие-то хитрые приемы для управления выводом HTML?
  • Вы просто говорите "черт с ним" и продолжаете создавать пользовательский элемент управления?

Это то, что я очень хочу придумать, так как я знаю, насколько хороший контроль разработки может сократить общее время разработки.

Я с нетерпением жду ваших ответов ^ _ ^

Ответы [ 6 ]

5 голосов
/ 20 августа 2008

Я говорю: продолжайте, пользовательский элемент управления отображается. Я нахожу, что в большинстве случаев композит может быть легче сделан и использован в UserControl, но все, кроме этого, и вам потребуется более тонкий уровень контроля (каламбур непреднамеренный), чтобы заслужить вашу собственную стратегию рендеринга.

Возможно, есть элементы управления, которые достаточно просты, чтобы заслуживать составного (например, текстовое поле, объединенное, например, со средством выбора даты на основе javascript / dhtml), но помимо этого одного примера, похоже, что пользовательские элементы управления представляют собой способ.

3 голосов
/ 20 августа 2008

Вот еще один метод расширения, который я использую для пользовательского рендеринга:

 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 голосов
/ 20 августа 2008

Роб, ты прав. Подход, который я упомянул, является своего рода гибридом. Преимущество наличия файлов ascx в том, что в каждом проекте, который я видел, дизайнеры чувствовали бы себя наиболее комфортно при редактировании реальной разметки, а с ascx вы и дизайнер можете работать отдельно. Если вы не планируете вносить изменения в CSS / разметку / дизайн в самих элементах управления позже, вы можете использовать пользовательский элемент управления. Как я уже сказал, мой подход важен только для более сложных сценариев (и это, вероятно, где вам нужен дизайнер:))

1 голос
/ 20 августа 2008

Использование пользовательских составных элементов управления имеет смысл в ситуации, когда у вас большое веб-приложение и вы хотите повторно использовать большие куски во многих местах. Тогда вы будете добавлять только дочерние элементы управления для тех, которые вы разрабатываете, вместо того, чтобы повторяться. Над большим проектом, над которым я недавно работал, мы сделали следующее:

  • Каждый составной элемент управления имеет контейнер. Используется как оболочка для всего, что находится внутри элемента управления.
  • Каждый составной элемент управления имеет шаблон. Файл ascx (без директивы <% Control%>), который содержит только разметку для шаблона.
  • Контейнер (сам по себе элемент управления) инициализируется из шаблона.
  • Контейнер предоставляет свойства для всех других элементов управления в шаблоне.
  • Вы используете this.Controls.Add ([the_container]) только в своем составном элементе управления.

Фактически вам нужен базовый класс, который позаботится об инициализации контейнера с указанным шаблоном, а также вызовет исключения, когда элемент управления не найден в шаблоне. Конечно, это может быть излишним в небольшом приложении. Если у вас нет повторного использования кода и разметки и вы хотите писать только простые элементы управления, лучше использовать пользовательские элементы управления.

1 голос
/ 20 августа 2008

Я часто использую составные элементы управления. Вместо переопределения Render или RenderContents, просто назначьте каждому элементу управления класс 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;
                           };
0 голосов
/ 16 сентября 2008

Возможно, вы сможете использовать эту технику, чтобы упростить время разработки:

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

По сути, вы создаете экземпляр пользовательского элемента управления во время выполнения с помощью метода LoadControl, затем передаете ему какой-то пакет состояний и затем присоединяете его к дереву элементов управления. Таким образом, ваш составной элемент управления на самом деле будет функционировать как контроллер, а файл .ascx будет похож на представление.

Это избавит вас от необходимости создавать экземпляр всего дерева элементов управления и стилизовать элемент управления в C #!

...