Подтвердить что ты не робот

ASP.NET/С#: DropDownList 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 находится на странице, а другие элементы управления на странице выполняют обратные передачи правильно, просто не это.

4b9b3361

Ответ 1

Включен ли ViewState?

Edit: Возможно, вам стоит пересмотреть переопределение функции рендеринга

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

и вместо этого добавьте dropdownlists в элемент управления и визуализируйте элемент управления с помощью RenderContents по умолчанию.

Edit: См. Ответ от Денниса, о котором я упоминал в своем предыдущем комментарии:

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

Ответ 2

Я не вижу, что вы добавляете эти элементы управления в иерархию управления. Попробуйте:

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

События не будут вызываться, если элемент управления не является частью иерархии управления.

Ответ 3

Вам нужно установить AutoPostBack в значение true для страны DropDownList.

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

    ddlCountries.AutoPostBack = true;

    // other stuff
}

Edit

Я пропустил, что вы это сделали. В этом случае вам нужно проверить, что ViewState включен.

Ответ 4

У меня была такая же проблема, но обойти ее, установив AutoPostBack в true, и на панели обновлений установите триггер для идентификатора элемента dropdownlist и имени события в 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?

Я не уверен, в каком случае у вас есть, но если это второй случай, я могу предложить какое-то предложение. Если это первый случай, то это FYI.

Во втором случае (обработчик событий никогда не срабатывает даже при запросе), вы можете попробовать следующие предложения:

  • Запросить Request.Params [ddlCountries.UniqueID] и посмотреть, имеет ли он значение. Если это произошло, вручную запустите обработчик событий.
  • Пока состояние просмотра включено, привязывайте только данные списка, если это не сообщение.
  • Если состояние просмотра должно быть выключено, тогда установите привязку данных списка в OnInit вместо OnLoad.

Остерегайтесь, что при вызове Control.DataBind() состояние просмотра и пост-обратной информации больше не будет доступно из элемента управления. В случае состояния просмотра, между post back, значения DropDownList будут сохранены (список не восстанавливается). Если вы выпустите еще один DataBind в OnLoad, он очистит данные состояния представления, и событие SelectedIndexChanged никогда не будет запущено.

В случае, когда состояние просмотра выключено, у вас нет выбора, кроме как перегруппировать список каждый раз. Когда происходит обратная связь, есть внутренние вызовы ASP.NET, чтобы заполнить значение из Request.Params соответствующим элементам управления, и я подозреваю, что они произошли в то время между OnInit и OnLoad. В этом случае восстановление значений списка в OnInit позволит системе правильно запускать события.

Спасибо за то, что вы читаете это время и приветствуете всех, чтобы исправить, если я ошибаюсь.