自定义服务器控件中动态添加的 PostBackTrigger 未正确呈现

发布于 2024-10-04 09:32:27 字数 2835 浏览 4 评论 0原文

我正在构建一个派生自 CompositeControl 的自定义服务器控件。
该控件包含许多子控件(Labels、DropDownList、ListSearchExtender 等)。它们全部驻留在 UpdatePanel 内。
该控件还发布事件。为此,我添加了两个属性:EnableCallBacks 和 CallBacksAsPostBacks。这两个属性应该配置更新面板的回发行为。

有什么想法正确的实现应该是什么样子吗?

我的实现方式遇到了一些问题:

  • PostBackTrigger 并不总是渲染到输出 html 中。

  • CreateChildControls 方法中同时使用 Triggers.Add(trigger)Controls.Add(_updatePanel) 会导致 PostBackTrigger 始终被渲染,即使我稍后将其删除(例如在 RenderControl() 或 PreRender() 内)。如果我不在这里添加触发器而是稍后添加,那么它永远不会被渲染。在此阶段,我还没有所有属性的正确值(例如 EnableCallBacksCallBacksAsPostBacks)。

  • 不可能将 Controls.Add(_updatePanel) 语句放在 RenderControl 方法内,因为它对于 AJAX 来说太晚了(最新的是 PreRender() 否则我会得到一个异常)。

  • 理想情况下,我会在 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);
}

I'm building a custom server control derived from CompositeControl.
The control contains a number of child controls (Labels, DropDownList, ListSearchExtender, etc). All of them reside inside an UpdatePanel.
The control also publishes events. For this I added two Properties: EnableCallBacks and CallBacksAsPostBacks. Those two properties should configure the postback behaviour of the update panel.

Any ideas what a correct implementation should look like?

I'm getting some problems with the way I implemented it:

  • the PostBackTrigger does not always get rendered into the output html.

  • Having both Triggers.Add(trigger) and Controls.Add(_updatePanel) inside the CreateChildControls methods leads to the PostBackTrigger always being rendered, even if I remove it later on (e.g. within RenderControl() or PreRender()). If I do not add the trigger here but later on, then it does never get rendered. At this stage I do not have the correct values of all my properties yet (e.g. EnableCallBacks and CallBacksAsPostBacks).

  • It is not possible to place the statement of Controls.Add(_updatePanel) inside the RenderControl-method due to it beeing too late for AJAX (latest ist PreRender() otherwise I get an exception).

  • Ideally I would instantiate all controls in CreateChildControls() and then set their values later on in e.g. PreRender or RenderControl

  • Having both statements in the PreRender method results in, that the trigger gets rendered corretly depending on my settings in the containing page, but I don't get the DropDownList populated with its data from the ViewState (on call/postbacks).

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦言归人 2024-10-11 09:32:27

您应该在 PreInit 中添加动态控件,以便事件正确触发。

将此事件用于以下用途:

  • 检查 IsPostBack 属性以
    判断这是否是第一个
    处理页面的时间。这
    IsCallback 和 IsCrossPagePostBack
    属性也已在此设置
    时间。
  • 创建或重新创建动态
    控制。
  • 设置母版页
    动态地。
  • 设定主题
    动态属性。
  • 读取或设置
    配置文件属性值。

You should add your dynamic controls in PreInit for the events to fire properly.

Use this event for the following:

  • Check the IsPostBack property to
    determine whether this is the first
    time the page is being processed. The
    IsCallback and IsCrossPagePostBack
    properties have also been set at this
    time.
  • Create or re-create dynamic
    controls.
  • Set a master page
    dynamically.
  • Set the Theme
    property dynamically.
  • Read or set
    profile property values.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文