Пользовательские элементы управления ASP.NET - Композиты
Резюме
Привет всем,
ОК, далее в мои приключения с настраиваемыми элементами управления...
Вкратце, вот что я узнал о трех основных "классах" пользовательских элементов управления. Пожалуйста, не стесняйтесь исправить меня, если это не так!
- UserControls - которые наследуются от UserControl и содержатся в файле ASCX. Они довольно ограничены в том, что они могут сделать, но являются быстрым и легким способом получить некоторую унификацию пользовательского интерфейса с поддержкой дизайнеров.
- Пользовательские составные элементы управления. Это элементы управления, которые наследуют от WebControl, где вы добавляете ранее существующие элементы управления в элемент управления в методе CreateChildControls. Это обеспечивает большую гибкость, но отсутствие поддержки дизайнера без дополнительного кодирования. Они очень портативны, поскольку они могут быть скомпилированы в DLL.
- Пользовательские визуализированные элементы управления. Подобно настраиваемым композитным элементам управления, они добавляются в проект веб-библиотеки управления. Передача элемента управления полностью контролируется программистом путем переопределения метода Render.
Мои мысли..
ОК, поэтому, играя с пользовательскими композитами, я нашел следующее:
- У вас мало/нет контроля над выходом HTML, что затрудняет "отладку".
- CreateChildControls (и последующие методы) могут повсеместно работать с Controls.Add(myControl).
- Я нашел таблицы рендеринга (будь то макет или контент), чтобы быть значительно неудобным.
Вопрос (ы)..
Итак, я признаю, что я новичок в этом, поэтому я мог быть вне базы с некоторыми из моих отмеченных выше замечаний.
- Вы используете Composites?
- Есть ли у вас какие-нибудь опрятные трюки для управления выходом HTML?
- Вы просто говорите "черт с ним" и продолжайте и создаете настраиваемый визуализированный элемент управления?
Своего-то я очень хочу, чтобы стать действительно твердым в моем сознании, так как я знаю, насколько хорошая управляющая разработка может сократить общее время разработки.
Я с нетерпением жду ваших ответов ^ _ ^
Ответы
Ответ 1
Я говорю, что вам нужно выполнить индивидуальное управление. Я нахожу, что в большинстве случаев композит может быть проще сделать и использовать в UserControl, но что-то кроме этого, и вам нужно будет иметь более тонкую степень контроля (каламбур непреднамеренно), чтобы заслужить вашу собственную стратегию рендеринга.
Там могут быть элементы управления, которые достаточно просты, чтобы заслужить композицию (например, текстовое поле в сочетании с japcript файлом, основанным на 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 в том, что в каждом проекте, который я видел, дизайнеры чувствовали бы себя наиболее комфортно с редактированием фактической разметки, а с помощью ascx вы и дизайнер могли бы работать отдельно. Если позже вы не планируете фактические изменения CSS/разметки/дизайна на элементах управления, вы можете пойти с настраиваемым визуализированным элементом управления. Как я уже сказал, мой подход применим только к более сложным сценариям (и, вероятно, там, где вам нужен дизайнер:))
Ответ 4
Я часто использую составные элементы управления. Вместо того, чтобы переопределять Render или RenderContents, просто назначьте каждый элемент управления CssClass и используйте таблицы стилей. Для нескольких элементов управления .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
Использование пользовательских составных элементов управления имеет смысл в ситуации, когда у вас есть большое веб-приложение и вы хотите повторно использовать большие куски во многих местах. Тогда вы только добавите дочерние элементы управления тех, которые вы разрабатываете, вместо того, чтобы повторять себя.
В большом проекте, который я недавно работал, мы сделали следующее:
- Каждый составной элемент управления имеет контейнер. Используется как обернутый для всего, что находится внутри элемента управления.
- Каждый составной элемент управления имеет шаблон. Файл ascx (без директивы <% Control% > ), который содержит только разметку для шаблона.
- Контейнер (сам по себе элемент управления) инициализируется из шаблона.
- Контейнер предоставляет свойства для всех других элементов управления в шаблоне.
- Вы только используете this.Controls.Add([the_container]) в своем составном элементе управления.
На самом деле вам нужен базовый класс, который позаботился бы об инициализации контейнера с указанным шаблоном, а также выдавал исключения, если элемент управления не найден в шаблоне. Конечно, это, вероятно, будет излишним в небольшом приложении. Если у вас нет повторного использования кода и разметки и вы хотите писать простые элементы управления, вам лучше использовать пользовательские элементы управления.
Ответ 6
Возможно, вы сможете использовать эту технику, чтобы упростить дизайн-время:
http://aspadvice.com/blogs/ssmith/archive/2007/10/19/Render-User-Control-as-String-Template.aspx
В принципе, вы создаете экземпляр пользовательского элемента управления во время выполнения с использованием метода LoadControl, затем передавайте ему какой-либо вид состояния, а затем присоединяете его к дереву управления. Таким образом, ваш составной элемент управления будет работать как контроллер, а файл .ascx будет похож на представление.
Это избавит вас от необходимости создавать экземпляр всего дерева управления и стилировать элемент управления на С#!