Я пытаюсь создать серверный элемент управления с дочерними элементами управления, которые являются исключительно производными от определенного класса.Дочерние элементы управления в этом случае также являются пользовательскими элементами управления сервера.Это конкретное веб-приложение использует файл темы оформления для применения стилей к этим дочерним элементам управления.
Ранее эти дочерние элементы управления использовались только в качестве дочерних элементов управления другого серверного элемента управления, который допускал любую разметку.Скин работает нормально, хотя с этой моделью есть некоторые недостатки.
Старая модель, которую я все еще должен поддерживать из соображений совместимости, выглядела как
<myns:FieldPanel ID="SomeId" runat="server" LabelText="SomeLabelText">
<myns:SomeFieldControl ID="SomeControlName" runat="server" SomeProperty="false" />
<myns:SomeOtherFieldControl ID="AnotherControl" runat="server" SomeProperty="false">
<Items>
<asp:ListItem Text="One" Value="1" />
<asp:ListItem Text="Dos" Value="2" />
<asp:ListItem Text="Trois" Value="3" />
</Items>
</myns:SomeOtherFieldControl>
</myns:FieldPanel>
The *Элемент управления 1008 * определен следующим образом:
[ParseChildren(false)]
public class FieldPanel : WebControl
{
public override void RenderBeginTag(HtmlTextWriter writer)
{
// some rendering
}
public override void RenderEndTag(HtmlTextWriter writer)
{
// some more rendering
}
public string PanelLabelCssClass { get; set; }
public string LabelText { get; set; }
}
И SomeFieldControl
, и SomeOtherFieldControl
наследуются от абстрактного базового класса с именем Field
.
Подобная разметка, в которой будет использоваться мой новый серверный элемент управления, будетbe
<myns:FieldTablePanel ID="AnotherId" runat="server" LabelText="OtherLabelText">
<Fields>
<myns:SomeFieldControl ID="SomeControlName" runat="server" SomeProperty="false" />
<myns:SomeOtherFieldControl ID="AnotherControl" runat="server" SomeProperty="false">
<Items>
<asp:ListItem Text="One" Value="1" />
<asp:ListItem Text="Dos" Value="2" />
<asp:ListItem Text="Trois" Value="3" />
</Items>
</myns:SomeOtherFieldControl>
</Fields>
</myns:FieldTablePanel>
FieldTablePanel
имеет намного больше кода, чем FieldPanel
, но некоторые основы:
[DefaultProperty(null)]
[ParseChildren(true)]
public class FieldTablePanel : FieldPanel, INamingContainer
{
private FieldCollection _fields;
private Table _innerTable;
public class FieldCollection : Collection<Field>, INamingContainer
{
// mainly standard Collection methods that I have to do something special with
}
[Bindable(false)]
[DefaultValue(null)]
[TemplateContainer(typeof(FieldCollection))]
[PersistenceMode(PersistenceMode.InnerProperty)]
// Note that FieldCollection does not work here
public Collection<Field> Fields
{
get
{
return _fields;
}
set
{
_innerTable.Rows.Clear();
_fields = new FieldCollection(_innerTable, Page, value);
}
}
}
Я, конечно, здесь упустил множество методов.У меня есть все рендеринг так, как я хочу , за исключением , что скины не применяются к SomeFieldControl
и SomeOtherFieldControl
, как они должны быть.Кроме того, при запуске кода значения Parent
и Page
для SomeFieldControl
и SomeOtherFieldControl
равны null
.Это не тот случай в унаследованном примере.
Я бы хотел не использовать просто ITemplate
для сбора внутренних элементов управления, если нет другого способа, так как я полагаюсь на все производные дочерние элементы управленияот Field
.Что мне здесь не хватает?Я могу предоставить больше кода по запросу.
Редактировать:
Файл скина (в данном случае Site.skin) имеет запись для каждого из пользовательских Field
контролирует а также FieldPanel
и FieldTablePanel
.Соответствующие части:
<myns:FieldPanel runat="server"
PanelLabelCssClass="formPanelLabel"
Width="100%"
/>
<myns:FieldTablePanel runat="server"
PanelLabelCssClass="formPanelLabel"
Width="100%"
/>
<myns:SomeFieldControl runat="server"
LabelCssClass="formFieldLabel"
ResourceClassKey="CommonResource"
RequiredErrorMessageResourceKey="RequiredMessageFormat"
/>
<myns:SomeOtherFieldControl runat="server"
LabelCssClass="formFieldLabel"
RequiredErrorMessageResourceKey="RequiredMessageFormat"
ResourceClassKey="CommonResource"
ChooseOneResourceKey="ChooseOneOption"
NoneResourceKey="NoneOption"
/>
Я внес небольшое изменение в определение FieldPanel
выше, добавив правильное имя свойства PanelLabelCssClass
, которое является классом CSS, применяемым к определенной метке.Базовый класс Field
имеет свойство под названием LabelCssClass
, которое снова применяет класс CSS к метке в элементе управления (которая работает, когда элемент управления находится в пределах FieldPanel
, но не когда элемент управления находится в разделе <Fields>
FieldTablePanel
).
Соответствующий CSS:
.formFieldLabel
{
font-family: Tahoma, Verdana, Arial, Helvetica, san;
font-size: smaller;
}
.formPanelLabel
{
font-family: Tahoma, Verdana, Arial, Helvetica, san;
color: #666666;
font-size: x-small;
}
Другое Редактирование:
К моему определению класса FieldTablePanel
я избавился от своего пользовательского переопределенияControls
(который просто в основном вернул коллекцию полей) и добавил:
protected override void OnInit(EventArgs e)
{
if (_fields != null)
{
_fields.ToList<Field>().ForEach(this.Controls.Add);
}
}
Не повезло.Скины все еще не применяются к элементам управления Field
.
Причиной, по которой у меня изначально было переопределение на Controls
, была попытка убедиться, что получение Controls
вернет ControlCollection
, который был всинхронизировать с Fields
всегда.Я добавил подобный код в сеттер в своем свойстве Fields
(в частности, добавив this.Controls.Clear();
и _fields.ToList().ForEach(this.Controls.Add);
в соответствующих местах) без изменений в результатах.Я мог бы попытаться манипулировать добавлением FieldCollection<code> to ensure that when a <code>Field
, которое добавляется в коллекцию Control
, но я не знаю, поможет ли это.
Еще одна вещь, которую я попытался, это добавить свой внутренний Table
как элемент управления для FieldTablePanel , но при этом просто выдавалась ошибка
Было найдено несколько элементов управления с одинаковым идентификатором '...'.Трассировка требует, чтобы элементы управления имели уникальные идентификаторы.
при переходе на страницу с элементом управления.