web-dev-qa-db-ja.com

ASP.NET / C#:サーバーコントロールのDropDownList SelectedIndexChangedが起動しない

私は基本的に2つのドロップダウンリストをバインドするサーバーコントロールを作成しています。1つは国用、もう1つは州用で、国の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();
    }
}

編集:ビューステートはページ上にあり、ページ上の他のコントロールはポストバックを正しく実行しますが、これだけではありません。

11
Jack Lawson

ビューステートはオンになっていますか?

編集:おそらく、レンダリング関数のオーバーライドを再検討する必要があります

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

代わりに、ドロップダウンリストをコントロールに追加し、デフォルトのRenderContentsを使用してコントロールをレンダリングします。

編集:前のコメントで触れたDennisからの回答を参照してください。

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );
5
Chris Ballance

これらのコントロールをコントロール階層に追加していることがわかりません。試してください:

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

コントロールがコントロール階層の一部でない限り、イベントは呼び出されません。

4
baretta

AutoPostBackDropDownListをtrueに設定する必要があります。

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

    ddlCountries.AutoPostBack = true;

    // other stuff
}

編集

あなたがこれをしたことを逃した。その場合は、ViewStateが有効になっていることを確認する必要があります。

3
Garry Shutler

私は同じ問題を抱えていましたが、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>
1
Wolexie

まず、はっきりさせておきたいことがあります。これはポストバック(サーバーへのトリップ)が発生しないのですか、それともポストバックは発生しますが、ddlCountry_SelectedIndexChangedイベントハンドラーに入ることはありませんか?

どちらのケースかはわかりませんが、2番目のケースの場合は、いくつかの提案をいたします。それが最初のケースである場合、以下が参考になります。

2番目のケース(要求が出されてもイベントハンドラーが起動しない)の場合は、次の提案を試してください。

  1. Request.Params [ddlCountries.UniqueID]をクエリして、値があるかどうかを確認します。ある場合は、手動でイベントハンドラーを起動します。
  2. ビューステートがオンである限り、ポストバックでない場合にのみリストデータをバインドします。
  3. ビューステートをオフにする必要がある場合は、リストデータバインドをOnLoadではなくOnInitに配置します。

Control.DataBind()を呼び出すと、ビューステートとポストバック情報がコントロールから利用できなくなることに注意してください。ビューステートがオンの場合、ポストバックの間、DropDownListの値はそのまま保持されます(リストは再バインドされません)。 OnLoadで別のDataBindを発行すると、ビューステートデータがクリアされ、SelectedIndexChangedイベントは発生しません。

ビューステートがオフの場合は、毎回リストを再バインドするしかありません。ポストバックが発生すると、Request.Paramsから適切なコントロールに値を入力するための内部ASP.NET呼び出しがあり、OnInitとOnLoadの間に発生したと思われます。この場合、OnInitでリスト値を復元すると、システムがイベントを正しく起動できるようになります。

これを読んでいただきありがとうございます。私が間違っている場合は、是正してください。

0