ASP.NET / C#:服务器控件中的 DropDownList SelectedIndexChanged 未触发

发布于 2024-07-14 03:17:43 字数 2944 浏览 4 评论 0原文

我正在创建一个服务器控件,它基本上绑定两个下拉列表,一个用于国家/地区,一个用于州,并更新国家/地区的 selectedindexchanged 事件的州下拉列表。 但是,它不会回发。 有什么想法吗? 将它们包装在 UpdatePanel 中的奖励点(存在渲染问题;也许是因为我没有可供引用的页面?)

这是我所拥有的(删除了一些额外的数据访问内容):

public class StateProv : WebControl
{
    public string SelectedCountry;
    public string SelectedState;

    private DropDownList ddlCountries = new DropDownList();
    private DropDownList ddlStates = new DropDownList();

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        IList<Country> countries = GetCountryList();
        IList<State> states = new List<State>();

        if (SelectedCountry != null && SelectedCountry != "")
        {
            states = GetStateList(GetCountryByShortName(SelectedCountry).CountryShortName);
        }
        else
        {
            states.Add(new State { CountryId = 0, Id = 0, StateLabelName = "No states available", StateLongName = "No states available", StateShortName = "" });
        }

        ddlCountries.DataSource = countries;
        ddlCountries.DataTextField = "CountryLongName";
        ddlCountries.DataValueField = "CountryShortName";
        ddlCountries.SelectedIndexChanged += new EventHandler(ddlCountry_SelectedIndexChanged);
        ddlCountries.AutoPostBack = true;

        ddlStates.DataSource = states;
        ddlStates.DataTextField = "StateLongName";
        ddlStates.DataTextField = "StateShortName";

        ddlCountries.DataBind();
        ddlStates.DataBind();

        if (!string.IsNullOrEmpty(SelectedCountry))
        {
            ddlCountries.SelectedValue = SelectedCountry;

            if (!string.IsNullOrEmpty(SelectedState))
            {
                ddlStates.SelectedValue = SelectedState;
            }
        }            
    }


    protected override void RenderContents(HtmlTextWriter output)
    {
        ddlCountries.RenderControl(output);
        ddlStates.RenderControl(output);
    }

    private IList<Country> GetCountryList()
    {
        //return stuff
    }

    private IList<State> GetStateList(Country country)
    {
        //return stuff
    }

    private IList<State> GetStateList(string countryAbbrev)
    {
        Country country = GetCountryByShortName(countryAbbrev);
        return GetStateList(country);
    }

    private Country GetCountryByShortName(string countryAbbrev)
    {
        IList<Country> list = dataAccess.RetrieveQuery<Country>();
        //return stuff
    }

    private IList<State> GetAllStates()
    {
        //return stuff
    }

    protected void ddlCountry_SelectedIndexChanged(object sender, EventArgs e)
    {
        IList<State> states = GetStateList(GetCountryList()[((DropDownList)sender).SelectedIndex]);
        ddlStates.DataSource = states;
        ddlStates.DataBind();
    }
}

编辑: Viewstate在页面上,页面上的其他控件都正确执行回发,只是不是这个。

I'm creating a server control that basically binds two dropdown lists, one for country and one for state, and updates the state dropdown on the country's selectedindexchanged event. However, it's not posting back. Any ideas why? Bonus points for wrapping them in an UpdatePanel (having rendering issues; maybe because I don't have a Page to reference?)

Here's what I have (with some extra data access stuff stripped out):

public class StateProv : WebControl
{
    public string SelectedCountry;
    public string SelectedState;

    private DropDownList ddlCountries = new DropDownList();
    private DropDownList ddlStates = new DropDownList();

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        IList<Country> countries = GetCountryList();
        IList<State> states = new List<State>();

        if (SelectedCountry != null && SelectedCountry != "")
        {
            states = GetStateList(GetCountryByShortName(SelectedCountry).CountryShortName);
        }
        else
        {
            states.Add(new State { CountryId = 0, Id = 0, StateLabelName = "No states available", StateLongName = "No states available", StateShortName = "" });
        }

        ddlCountries.DataSource = countries;
        ddlCountries.DataTextField = "CountryLongName";
        ddlCountries.DataValueField = "CountryShortName";
        ddlCountries.SelectedIndexChanged += new EventHandler(ddlCountry_SelectedIndexChanged);
        ddlCountries.AutoPostBack = true;

        ddlStates.DataSource = states;
        ddlStates.DataTextField = "StateLongName";
        ddlStates.DataTextField = "StateShortName";

        ddlCountries.DataBind();
        ddlStates.DataBind();

        if (!string.IsNullOrEmpty(SelectedCountry))
        {
            ddlCountries.SelectedValue = SelectedCountry;

            if (!string.IsNullOrEmpty(SelectedState))
            {
                ddlStates.SelectedValue = SelectedState;
            }
        }            
    }


    protected override void RenderContents(HtmlTextWriter output)
    {
        ddlCountries.RenderControl(output);
        ddlStates.RenderControl(output);
    }

    private IList<Country> GetCountryList()
    {
        //return stuff
    }

    private IList<State> GetStateList(Country country)
    {
        //return stuff
    }

    private IList<State> GetStateList(string countryAbbrev)
    {
        Country country = GetCountryByShortName(countryAbbrev);
        return GetStateList(country);
    }

    private Country GetCountryByShortName(string countryAbbrev)
    {
        IList<Country> list = dataAccess.RetrieveQuery<Country>();
        //return stuff
    }

    private IList<State> GetAllStates()
    {
        //return stuff
    }

    protected void ddlCountry_SelectedIndexChanged(object sender, EventArgs e)
    {
        IList<State> states = GetStateList(GetCountryList()[((DropDownList)sender).SelectedIndex]);
        ddlStates.DataSource = states;
        ddlStates.DataBind();
    }
}

Edit: Viewstate is on the page, and other controls on the page perform postbacks correctly, just not this.

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

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

发布评论

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

评论(5

白色秋天 2024-07-21 03:17:43

视图状态是否打开?

编辑:
也许您应该重新考虑覆盖呈现函数

  protected override void RenderContents(HtmlTextWriter output)
    {
        ddlCountries.RenderControl(output);
        ddlStates.RenderControl(output);
    }

,而是将下拉列表添加到控件并使用默认的 RenderContents 呈现控件。

编辑:
请参阅我在之前的评论中提到的丹尼斯的答案:

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );

Is Viewstate turned on?

Edit:
Perhaps you should reconsider overriding the rendering function

  protected override void RenderContents(HtmlTextWriter output)
    {
        ddlCountries.RenderControl(output);
        ddlStates.RenderControl(output);
    }

and instead add the dropdownlists to the control and render the control using the default RenderContents.

Edit:
See the answer from Dennis which I alluded to in my previous comment:

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );
七月上 2024-07-21 03:17:43

我看不到您正在将这些控件添加到控件层次结构中。
Try:

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );

除非控件是控件层次结构的一部分,否则不会调用事件。

I can't see that you're adding these controls to the control hierarchy.
Try:

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );

Events won't be invoked unless the control is part of the control hierarchy.

緦唸λ蓇 2024-07-21 03:17:43

您需要将国家/地区 DropDownListAutoPostBack 设置为 true。

protected override void OnLoad(EventArgs e)
{
    // base stuff

    ddlCountries.AutoPostBack = true;

    // other stuff
}

编辑

我错过了你所做的事情。 在这种情况下,您需要检查 ViewState 是否已启用。

You need to set AutoPostBack to true for the Country DropDownList.

protected override void OnLoad(EventArgs e)
{
    // base stuff

    ddlCountries.AutoPostBack = true;

    // other stuff
}

Edit

I missed that you had done this. In that case you need to check that ViewState is enabled.

忆伤 2024-07-21 03:17:43

我遇到了同样的问题,但通过将 AutoPostBack 设置为 true 并在更新面板中将触发器设置为下拉列表控件 id 并将事件名称设置为 SelectedIndexChanged 来解决它,例如

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always" enableViewState="true">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="ddl1" EventName="SelectedIndexChanged" />
        </Triggers>
        <ContentTemplate>
            <asp:DropDownList ID="ddl1" runat="server" ClientIDMode="Static" OnSelectedIndexChanged="ddl1_SelectedIndexChanged" AutoPostBack="true" ViewStateMode="Enabled">
                <asp:ListItem Text="--Please select a item--" Value="0" />
            </asp:DropDownList>
        </ContentTemplate>
    </asp:UpdatePanel>

I had the same problem but got round it by setting AutoPostBack to true and in an update panel set the trigger to the dropdownlist control id and event name to SelectedIndexChanged e.g.

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Always" enableViewState="true">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="ddl1" EventName="SelectedIndexChanged" />
        </Triggers>
        <ContentTemplate>
            <asp:DropDownList ID="ddl1" runat="server" ClientIDMode="Static" OnSelectedIndexChanged="ddl1_SelectedIndexChanged" AutoPostBack="true" ViewStateMode="Enabled">
                <asp:ListItem Text="--Please select a item--" Value="0" />
            </asp:DropDownList>
        </ContentTemplate>
    </asp:UpdatePanel>
飞烟轻若梦 2024-07-21 03:17:43

首先,我想澄清一件事。 这是回发(返回服务器)永远不会发生,还是回发发生,但它永远不会进入 ddlCountry_SelectedIndexChanged 事件处理程序?

我不确定你遇到的是哪种情况,但如果是第二种情况,我可以提供一些建议。 如果是第一种情况,那么以下仅供参考。

对于第二种情况(即使发出请求,事件处理程序也不会触发),您可能需要尝试以下建议:

  1. 查询 Request.Params[ddlCountries.UniqueID] 并查看它是否具有值。 如果有,请手动触发事件处理程序。
  2. 只要视图状态打开,只有在不是回发时才绑定列表数据。
  3. 如果视图状态必须关闭,则将列表数据绑定放在 OnInit 而不是 OnLoad 中。

请注意,调用 Control.DataBind() 时,控件将不再提供视图状态和回发信息。 在视图状态打开的情况下,在回发之间,DropDownList 的值将保持不变(列表不会反弹)。 如果您在 OnLoad 中发出另一个 DataBind,它将清除其视图状态数据,并且永远不会触发 SelectedIndexChanged 事件。

在视图状态关闭的情况下,你别无选择,只能每次都重新绑定列表。 当发生回发时,会有内部 ASP.NET 调用将 Request.Params 中的值填充到适当的控件,我怀疑发生在 OnInit 和 OnLoad 之间的时间。 在这种情况下,恢复 OnInit 中的列表值将使系统能够正确触发事件。

感谢您花时间阅读本文,如有错误欢迎大家指正。

First, I would like to clarify something. Is this a post back (trip back to server) never occur, or is it the post back occurs, but it never gets into the ddlCountry_SelectedIndexChanged event handler?

I am not sure which case you are having, but if it is the second case, I can offer some suggestion. If it is the first case, then the following is FYI.

For the second case (event handler never fires even though request made), you may want to try the following suggestions:

  1. Query the Request.Params[ddlCountries.UniqueID] and see if it has value. If it has, manually fire the event handler.
  2. As long as view state is on, only bind the list data when it is not a post back.
  3. If view state has to be off, then put the list data bind in OnInit instead of OnLoad.

Beware that when calling Control.DataBind(), view state and post back information would no longer be available from the control. In the case of view state is on, between post back, values of the DropDownList would be kept intact (the list does not to be rebound). If you issue another DataBind in OnLoad, it would clear out its view state data, and the SelectedIndexChanged event would never be fired.

In the case of view state is turned off, you have no choice but to rebind the list every time. When a post back occurs, there are internal ASP.NET calls to populate the value from Request.Params to the appropriate controls, and I suspect happen at the time between OnInit and OnLoad. In this case, restoring the list values in OnInit will enable the system to fire events correctly.

Thanks for your time reading this, and welcome everyone to correct if I am wrong.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文