ASP.NET / C #: DropDownList SelectedIndexChanged в серверном элементе управления не срабатывает - PullRequest
11 голосов
/ 20 февраля 2009

Я создаю серверный элемент управления, который в основном связывает два раскрывающихся списка, один для страны и один для штата, и обновляет раскрывающийся список состояний для события selectedindexbound страны. Однако, это не отправляет назад. Есть идеи почему? Бонусные баллы за их обертывание в 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 находится на странице, и другие элементы управления на странице выполняют обратные передачи правильно, только не это.

Ответы [ 5 ]

5 голосов
/ 20 февраля 2009

Viewstate включено?

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

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

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

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

Controls.Add ( ddlCountries );
Controls.Add ( ddlStates );
4 голосов
/ 20 февраля 2009

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

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

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

3 голосов
/ 20 февраля 2009

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

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

    ddlCountries.AutoPostBack = true;

    // other stuff
}

Редактировать

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

1 голос
/ 14 ноября 2011

У меня была та же проблема, но я обошел ее, установив для AutoPostBack значение true, и на панели обновлений установил триггер для идентификатора элемента управления выпадающего списка и имя события 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>
0 голосов
/ 20 февраля 2009

Во-первых, я хотел бы кое-что уточнить. Является ли это возвращением сообщения (возвращением на сервер), или возвращение сообщения происходит, но оно никогда не попадает в обработчик событий ddlCountry_SelectedIndexChanged?

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

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

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

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

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

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

...