Я создаю настраиваемый серверный элемент управления, производный от CompositeControl
.
Этот элемент управления содержит несколько дочерних элементов управления (Labels, DropDownList, ListSearchExtender и т. Д.). Все они находятся внутри UpdatePanel
.
Элемент управления также публикует события. Для этого я добавил два свойства: EnableCallBacks и CallBacksAsPostBacks. Эти два свойства должны настраивать поведение обратной передачи панели обновлений.
Есть идеи, как должна выглядеть правильная реализация?
У меня проблемы с тем, как я это реализовал:
PostBackTrigger не всегда отображается в выходном HTML.
Наличие как
Triggers.Add(trigger)
, так иControls.Add(_updatePanel)
внутри методовCreateChildControls
приводит к тому, что PostBackTrigger всегда отображается, даже если я удалю его позже (например, в RenderControl () или PreRender ()). Если я не добавлю триггер здесь, но позже, он никогда не будет отрисован. На данном этапе у меня еще нет правильных значений всех моих свойств (например,EnableCallBacks
иCallBacksAsPostBacks
).Невозможно разместить оператор
Controls.Add(_updatePanel)
внутри метода RenderControl, потому что он слишком поздно для AJAX (последний istPreRender()
, иначе я получаю исключение).В идеале я бы создал все элементы управления в CreateChildControls (), а затем установил их значения позже, например, в PreRender или RenderControl
Наличие обоих операторов в методе
PreRender
приводит к тому, что триггер правильно отображается в зависимости от моих настроек на содержащей странице, но я не получаю DropDownList, заполненный его данными из ViewState (при вызове / обратной передаче).
protected override void CreateChildControls()
{
base.CreateChildControls();
_updatePanel = new UpdatePanel();
_updatePanel.ID = "FprDropDownList_UpPnl";
_updatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;
_label = new FprLabel();
_label.ID = "FprDropDownList_Lbl";
_updatePanel.ContentTemplateContainer.Controls.Add(_label);
_dropDownList = new DropDownList();
_dropDownList.ID = "FprDropDownList_Ddl";
_dropDownList.CssClass = "fprDropDownList";
_dropDownList.AutoPostBack = true;
_updatePanel.ContentTemplateContainer.Controls.Add(_dropDownList);
_label.AssociatedControlID = _dropDownList.ClientID;
_listSearchExtender = new ListSearchExtender();
_listSearchExtender.ID = "FprDropDownList_Lse";
_listSearchExtender.TargetControlID = _dropDownList.ClientID;
_listSearchExtender.PromptPosition = ListSearchPromtPosition;
_listSearchExtender.PromptCssClass = "fprListSearchExtender";
_updatePanel.ContentTemplateContainer.Controls.Add(_listSearchExtender);
_ddlPostBackTrigger = new PostBackTrigger();
_ddlPostBackTrigger.ControlID = _dropDownList.ClientID;
//_updatePanel.Triggers.Add(_ddlPostBackTrigger);
Controls.Add(_updatePanel);
}
protected override void OnPreRender(EventArgs pE)
{
if (EnableCallBacks)
{
_dropDownList.SelectedIndexChanged += DropDownList_SelectedIndexChanged;
}
if (EnableCallBacks && CallBacksAsPostBacks)
{
_updatePanel.Triggers.Add(_ddlPostBackTrigger);
}
//Controls.Add(_updatePanel);
base.OnPreRender(pE);
}
public override void RenderControl(HtmlTextWriter pWriter)
{
// Do some things... like set Enable-state of child controls
base.RenderControl(pWriter);
}