【问题标题】:How can I get an UpdatePanel to intercept a CompositeControl's DropDownList如何让 UpdatePanel 拦截 CompositeControl 的 DropDownList
【发布时间】:2008-10-22 13:11:22
【问题描述】:

我有一个包含 DropDownList 的 CompositeControl。

我已将 DropDownList 的 AutoPostBack 属性设置为 true。

在页面上,我有:

<asp:UpdatePanel ID="UpdatePanel" runat="server">
    <ContentTemplate>
        <MyControl:Control ID="CustomControl" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel>

我也尝试过设置 ChildrenAsTriggers="true"UpdateMode="Always,",但都没有解决问题。

问题是UpdatePanel 没有拦截CompositeControl 的DropDownList 的回发。 (更改 DropDownList 时正在执行完整的 POST)

如何让 UpdatePanel 处理回发?

谢谢!

编辑 -- 请求的信息

Country 和 states 都是 CompositeControl 中的 DropDownLists。

country.SelectedIndexChanged += new EventHandler(country_SelectedIndexChanged);

protected void country_SelectedIndexChanged(Object sender, EventArgs e)
{
    states.DataSource = XXX;
    states.DataBind();
}

【问题讨论】:

  • 您在页面上或您的控制范围内是否还有其他 UpdatePanel?此外,您能否显示 DropDownList 的 SelectedIndexChanged 事件处理程序和委托定义的代码。
  • 不,我在页面或控件中没有任何其他 UpdatePanel。我将编辑我的帖子以显示处理程序。

标签: asp.net asp.net-ajax


【解决方案1】:

好的,所以这可能不是最佳答案,但我认为您遇到的问题是 UpdatePanel 无法看到子控件的事件。好消息是,它很容易修复。假设您有一个控件(CatchMyEvent,顺便说一句,这是一个非常聪明的名字),它上面有一个 DropDownList。现在,您希望父页面在该列表上看到 SelectedIndexChanged 事件并更新标签以匹配 SelectedItem.Text。事实上,父母真的不能这样做。所以让我们改变一下:

public partial class CatchMyEvent : System.Web.UI.UserControl
{
    public delegate void ChangedIndex(object sender, EventArgs e);
    public event ChangedIndex SelectedIndexChanged;

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        dropDownListThrow.SelectedIndexChanged += new EventHandler(dropDownListThrow_SelectedIndexChanged);
        labelOutput.Text = "no";
    }

    public void dropDownListThrow_SelectedIndexChanged(object sender, EventArgs e)
    {
        labelOutput.Text = ((DropDownList)sender).SelectedItem.Text;
        if(SelectedIndexChanged != null)
        {
            SelectedIndexChanged(sender, e);
        }
    }
}

基本上我所做的只是让控件捕获 DropDownList 的 SelectedIndexChanged 事件并触发它,以便任何父页面或控件都可以看到它。基本上我所做的就是把它传递下去。现在在父页面上,它真的很容易捕获。

您只需要添加一个带有触发器的 UpdatePanel:

<asp:AsyncPostBackTrigger ControlID="catchMyEventMain" EventName="SelectedIndexChanged" />

...当然也可以将其添加到父页面的代码中:

protected override void OnInit(EventArgs e)
{
    base.OnInit(e);
    catchMyEventMain.SelectedIndexChanged += dropDownListThrow_SelectedIndexChanged;
}

public void dropDownListThrow_SelectedIndexChanged(object sender, EventArgs e)
{        
    labelSelectedValue.Text = ((DropDownList)sender).SelectedItem.Text;
}

其中标签是前面提到的标签。然后让奇迹发生。

还有两个注意事项:

1) 不要像我在测试时那样傻,忘记将 DropDownList 上的 AutoPostBack 属性设置为 true。

2) 确保标签在 UpdatePanel 的 ContentTemplate 中。

希望这会有所帮助。

【讨论】:

  • 我在 CompositeControl 的构造函数中添加了一个处理程序,但在处理程序中,SelectedIndexChanged 总是 == null,所以它永远不会被触发。
  • 这意味着父控件没有挂接到该事件。不确定您是否知道,但以防万一 if not null 检查是一种确保某事在某处处理该事件的方法。 catchMyEventMain.SelectedIndexChanged += dropDownListThrow_SelectedIndexChanged;在父页面上。
  • 基本上确保您的父页面正在处理您在子控件上创建的 SelectedIndexChanged 事件。
【解决方案2】:

我在 ListView 中的 UpdatePanel 中有重复的子控件(文本框和标签)。

更改文本框会导致完全(同步)回发。

我添加了 PAGE 元素(.aspx 页面的第一行):ClientIDMode="AutoID"

这解决了我的问题,现在只有 UpdatePanel 会根据需要刷新。

【讨论】:

  • 奇怪的是,我遇到了类似的问题,而 ClientIDMode="AutoID" 最终成为解决它的正确方法......
  • 5 小时调试我的代码并最终找到这篇文章。有效! Microsoft 的 .NET 框架中一定存在错误。非常感谢!!!!
【解决方案3】:

我在 BuildControlHierarchy 的末尾做了以下操作:

        ...
        if (DesignMode || Page == null) return;

        var sm = ScriptManager.GetCurrent(Page);
        if (sm == null)
        {
            throw new MissingFieldException("The ScriptManager is needed on the page!");
        }
        sm.RegisterAsyncPostBackControl(<control which initiates async postback>);

【讨论】:

    【解决方案4】:

    只需确保整个层次结构中的每个控件都有一个 ID 集。

    this question

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多