【问题标题】:ASP.NET / C#: DropDownList SelectedIndexChanged in server control not firingASP.NET / C#:服务器控件中的 DropDownList SelectedIndexChanged 未触发
【发布时间】:2010-10-08 21:21:47
【问题描述】:

我正在创建一个服务器控件,它基本上绑定了两个下拉列表,一个用于国家,一个用于州,并更新国家/地区的 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();
    }
}

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

【问题讨论】:

  • 可能不算作答案,但 Ajax 控制工具包在更新面板中提供了您想要的内容:asp.net/AJAX/AjaxControlToolkit/Samples/CascadingDropDown/…
  • 是的;不过,我已经发誓永远退出 ACT。绝对垃圾IMO;实际上,我正在为我的项目构建一个替代品,因为我们只能让 CCD 控件与 Web 服务一起工作,这有其他含义。

标签: c# asp.net drop-down-menu custom-server-controls selectedindexchanged


【解决方案1】:

Viewstate 是否开启?

编辑: 或许你应该重新考虑重写渲染函数

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

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

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

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

【讨论】:

  • 这看起来很有希望。如果 ViewState 处于关闭状态(在下拉列表或其任何父项上 - 一直到页面),则该事件不会触发。 (它应该回发……)
  • 视图状态在控件所在的页面上。在这个 .cs 文件中,我需要做什么特定于该控件的操作吗?
  • 快速检查的方法是查看源代码,看看是否有任何内容存储在视图状态中
  • 是的;它在页面上打开,其他回发控件正在工作。
  • 你拯救了我的一天 :) 和免费的啤酒!
【解决方案2】:

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

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

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

【讨论】:

  • 是 - 并且在加载之前的事件中执行此操作(例如 Init);否则,当 ViewState 重新加载时,控件将不会位于正确的位置。
  • 是的,或者最好在 override CreateChildControls
  • 正要说同样的话...应该创建它们并将它们添加到 CreateChildControls 中的 Controls 集合中。你也可以删除渲染覆盖。
  • 谢谢!绝对是这样。
【解决方案3】:

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

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

    ddlCountries.AutoPostBack = true;

    // other stuff
}

编辑

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

【讨论】:

  • 他的行是否“ddlCountries.AutoPostBack = true;”不这样做?
【解决方案4】:

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

【讨论】:

    【解决方案5】:

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

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

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

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

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

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

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

    【讨论】:

    • 当我更改选定的列表项时,它根本没有访问服务器。不过,谢谢;这是我必须在其他领域解决的另一个问题,这是很好的信息。
    • 我明白了;那么我认为 Dennis Myren 的答案可能是正确的:这两个 DropDownList 不在控制树中,所以即使它们被正确呈现,ASP.NET 事件处理机制根本无法从 Page 级别看到存在,因此没有事件被触发。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-21
    • 1970-01-01
    • 2016-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多