选定索引已更改事件未在子控件中触发

本文关键字:控件 事件 索引 | 更新日期: 2023-09-27 18:32:39

我有一个 asp.net 控件,当按下按钮时,它引用了一个用户控件(弹出窗口(。 按下按钮时,我在弹出用户控件中找到下拉列表,并设置它的选定值。

  protected void btnMyBUtton_Click(object sender, EventArgs args)
    {
        pnlUserControl_ModalPopupExtender.Show();
        if (ddParent.SelectedIndex > 0)
        {
            DropDownList dd = ucMyControl.FindControlRecursive("ddChild") as DropDownList;
            dd.SelectedValue = ddParent.SelectedValue;
        }
    }

在弹出用户控件中,我预计 SelectedIndexChanged 事件会触发。然而,事实并非如此。 知道为什么会这样吗?

我的子控件(仅相关代码(的标记如下:

<asp:FormView ID="myForm" runat="server" DataSourceID="dsMyDS" DefaultMode="Insert">
<EditItemTemplate>
    <asp:Panel runat="server">
        <table>
            <tr>
                <td>
                    <asp:Label Text="Name" runat="server" /></td>
                <td>
                    <asp:DropDownList ID="ddChild" runat="server" DataSourceID="ddDS" DataMember="" DataValueField="Id" DataTextField="Name" SelectedValue='<%# Bind("Id") %>' AutoPostBack="true" OnSelectedIndexChanged="ddChild_SelectedIndexChanged" OnDataBound="ddChild_DataBound" />
                </td>
            </tr>
        </table>
        <table>
            <tr>
                <td>
                    <br />
                    <asp:Button ID="btInsertOk" runat="server" Text="Add" CommandName="Insert" />
                    <asp:Button ID="btInsertCancel" runat="server" Text="Cancel" />
                </td>
            </tr>
        </table>
    </asp:Panel>
</EditItemTemplate>

提前谢谢。

选定索引已更改事件未在子控件中触发

更改代码隐藏中的选定值时,事件似乎不会触发。仅当用户通过在下拉列表中选择新值来更改值时,才会触发它。

您可以做的是将代码从事件中移出到单独的方法中,并从事件中调用该方法。当用户通过 UI 进行更改时,您的事件仍将触发。

protected void ddChild_SelectedIndexChanged(object sender, EventArgs e)
{
    ImportantStuff();
}
public void ImportantStuff()
{
    // everything that was in the SelectedIndexChanged event
}

然后在按钮单击事件中,存储旧的SelectedIndex值,进行更改,并将其与新的SelectedIndex值进行比较。如果它们不同,则所选索引已更改,您可以调用上述 SelectedIndexChanged 事件调用的相同方法:

protected void btnMyBUtton_Click(object sender, EventArgs args)
{
    pnlUserControl_ModalPopupExtender.Show();
    if (ddParent.SelectedIndex > 0)
    {
        DropDownList dd = ucMyControl.FindControlRecursive("ddChild") as DropDownList;
        var oldIndex = dd.SelectedIndex;
        dd.SelectedValue = ddParent.SelectedValue;
        var newIndex = dd.SelectedIndex;
        if (oldIndex != newIndex)  // selected index changed
            ImportantStuff();
    }
}

正如 Sam 所指出的,ImportantStuff() 方法应该在 UserControl 中是公共的,因此您可以从 UserControl 所在的页面访问它。

更好的是,假设"重要内容"不需要访问 UserControl 中的其他控件,您可以将该代码移动到单独的类中,然后从两个位置调用它,而无需 Page 调用 UserControl 中的公共方法(您的代码保持更简洁,更少纠结(。

SelectedIndexChanged事件有点令人困惑。根据MSDN此方法的定义是

当从列表控件中选择的内容在帖子之间更改时发生 到服务器。

因此,在这种情况下,即使您未从 DropDownList 中选择任何内容,此事件也会在下一次回发中触发(因为没有AutoPostback(。这是因为所选索引在回发之间发生了更改。不确定这是否是一个错误。我做了一点测试,这是真的。如果我错了,请纠正我。我今天学到了一些新东西:)

溶液

问题的解决方案是@GrantWinney建议的。将 SelectedIndexChanged 事件中的常见功能提取到公共事件中,并在下一行之后调用该方法。

dd.SelectedValue = ddParent.SelectedValue;

如果您的 ddChild 控件采用相同的方法,您可以通过按如下方式调用它来调用它SelectedIndexChanged事件

ddChild_SelectedIndexChanged(sender, args);

我假设您正在ajax弹出窗口中显示您的用户控件。您可以尝试像这样弹出您的用户控件:

<asp:Panel ID="pseudopopup" runat="server" visible="false">
 <table style="position: fixed; z-index: 1; left: 0px; top: 0px"   border="0"  width="100%" height="100%">
    <tr>
        <td valign="top"  align="center"  >
        <div style="margin:top:60px; width:600px" class="shadow"
        <ascx:WebUserControl ID="mycontrol" runat="server" />   
        </div> 
        </td>        
    </tr>
    </table> 
 </asp:Panel>

在代码隐藏中:

protected void btnMyBUtton_Click(object sender, EventArgs args)
pseudopopup.Visible = true;