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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/570294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:39:48  来源:igfitidea点击:

ASP.NET / C#: DropDownList SelectedIndexChanged in server control not firing

c#asp.netdrop-down-menucustom-server-controlsselectedindexchanged

提问by Hyman Lawson

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?)

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

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.

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

采纳答案by Chris Ballance

Is Viewstate turned on?

是否开启了 Viewstate?

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.

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

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

编辑:请参阅我在之前的评论中提到的 Dennis 的回答:

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

回答by Garry Shutler

You need to set AutoPostBackto true for the Country DropDownList.

您需要AutoPostBack为 Country设置为 true 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.

我想念你这样做了。在这种情况下,您需要检查是否启用了 ViewState。

回答by TimeSpace Traveller

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?

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

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

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

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.

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

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

感谢您花时间阅读本文,如果我错了,欢迎大家纠正。

回答by baretta

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.

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

回答by Wolexie

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.

我遇到了同样的问题,但通过将 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>