web-dev-qa-db-fra.com

ASP.NET/C #: DropDownList SelectedIndexChanged dans le contrôle serveur ne se déclenche pas

Je crée un contrôle serveur qui lie en gros deux listes déroulantes, une pour le pays et l'autre pour l'état, et met à jour le menu déroulant d'état sur l'événement sélectionnéindexchanged du pays. Cependant, cela ne revient pas. Des idées pourquoi? Points bonus pour les intégrer dans un UpdatePanel (problèmes de rendu; peut-être parce que je n'ai pas de page à référencer?)

Voici ce que j'ai (avec quelques éléments supplémentaires d'accès aux données supprimés):

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 est sur la page, et d'autres contrôles sur la page effectuent correctement les publications, mais pas cela.

11
Jack Lawson

Viewstate est-il activé?

Edit: Peut-être devriez-vous reconsidérer le remplacement de la fonction de rendu

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

et à la place, ajoutez les listes déroulantes au contrôle et effectuez le rendu à l'aide du RenderContents par défaut.

Edit: Voir la réponse de Dennis à laquelle j'ai fait allusion dans mon précédent commentaire:

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

Je ne vois pas que vous ajoutiez ces contrôles à la hiérarchie des contrôles. Essayez:

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

Les événements ne seront invoqués que si le contrôle fait partie de la hiérarchie des contrôles.

4
baretta

Vous devez définir AutoPostBack sur true pour le pays DropDownList.

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

    ddlCountries.AutoPostBack = true;

    // other stuff
}

Modifier

Ça m'a manqué que tu aies fait ça. Dans ce cas, vous devez vérifier que ViewState est activé.

3
Garry Shutler

J'avais le même problème, mais je l'ai corrigé en définissant AutoPostBack sur true et, dans un panneau de mise à jour, définissez le déclencheur sur l'ID de contrôle dropdownlist et le nom de l'événement sur SelectedIndexChanged, par exemple.

    <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

Tout d'abord, je voudrais clarifier quelque chose. S'agit-il d'une publication arrière (retour sur le serveur), ou est-ce que la publication a lieu, mais elle n'entre jamais dans le gestionnaire d'événements ddlCountry_SelectedIndexChanged?

Je ne sais pas quel cas vous avez, mais si c'est le deuxième cas, je peux faire une suggestion. Si c'est le premier cas, alors ce qui suit est FYI.

Pour le second cas (le gestionnaire d'événements ne se déclenche jamais malgré la demande), vous pouvez essayer les suggestions suivantes:

  1. Interrogez le Request.Params [ddlCountries.UniqueID] et voyez s'il a une valeur. Si c'est le cas, déclenchez manuellement le gestionnaire d'événements.
  2. Tant que l'état d'affichage est activé, ne liez les données de la liste que s'il ne s'agit pas d'une publication.
  3. Si l'état d'affichage doit être désactivé, placez la liaison de données de liste dans OnInit au lieu de OnLoad.

Notez que lors de l'appel de Control.DataBind (), les informations d'affichage et de publication ne sont plus disponibles à partir du contrôle. Dans le cas où l'état d'affichage est activé, entre les révisions, les valeurs de DropDownList seraient conservées telles quelles (la liste ne doit pas être rebondie). Si vous émettez un autre DataBind dans OnLoad, ses données d'état d'affichage seront effacées et l'événement SelectedIndexChanged ne sera jamais déclenché.

Dans le cas où l'état d'affichage est désactivé, vous n'avez pas d'autre choix que de reconfigurer la liste à chaque fois. Lorsqu'une publication a lieu, il existe des appels internes ASP.NET pour renseigner la valeur de Request.Params sur les contrôles appropriés, et je suppose que cela se produit entre OnInit et OnLoad. Dans ce cas, la restauration des valeurs de liste dans OnInit permettra au système de déclencher correctement les événements.

Merci pour votre temps à lire ceci, et invite tout le monde à corriger si je me trompe.

0
TimeSpace Traveller