Пользовательский список RadioButtonList теряет значение при обратной передаче

#asp.net #custom-controls #radiobuttonlist

#asp.net #пользовательские элементы управления #radiobuttonlist

Вопрос:

Я создал пользовательский RadioButtonList, который отображается как неупорядоченный список на основе аналогичного примера кода для пользовательского списка флажков.

Но по какой-то причине выбранный мной элемент не сохраняется при выполнении обратной передачи. Единственный метод, который я переопределил, — это Render-method:

 [ToolboxData( "<{0}:ULRadioButtonList runat=server></{0}:ULRadioButtonList>" )]
public class ULRadioButtonList : RadioButtonList {
    protected override void Render( HtmlTextWriter writer ) {
        Controls.Clear();

        string input = "<input id={0}{1}{0} name={0}{2}{0} type={0}radio{0} value={0}{3}{0}{4} />";
        string label = "<label for={0}{1}{0}>{2}</label>";
        string list = "<ul>";

        if ( !String.IsNullOrEmpty( CssClass ) ) {
            list = "<ul class=""   CssClass   "">";
        }

        writer.WriteLine( list );

        for ( int index = 0; index < Items.Count; index   ) {
            writer.Indent  ;
            writer.Indent  ;

            writer.WriteLine( "<li>" );

            writer.Indent  ;

            StringBuilder sbInput = new StringBuilder();
            StringBuilder sbLabel = new StringBuilder();

            sbInput.AppendFormat(
                input,
                """,
                base.ClientID   "_"   index.ToString(),
                base.UniqueID,
                base.Items[index].Value,
                (base.Items[index].Selected ? " checked=""" : "")
            );

            sbLabel.AppendFormat(
                label,
                """,
                base.ClientID   "_"   index.ToString(),
                base.Items[index].Text
            );

            writer.WriteLine( sbInput.ToString() );
            writer.WriteLine( sbLabel.ToString() );

            writer.Indent = 1;

            writer.WriteLine( "</li>" );

            writer.WriteLine();

            writer.Indent = 1;
            writer.Indent = 1;
        }

        writer.WriteLine( "</ul>" );
    }
}
  

Я что-то забыл? Если я использую обычный ASP.NET RadioButtonList выбранный мной элемент сохраняется после обратной передачи, поэтому больше ничего не переопределяет мое значение; это как-то связано с пользовательским элементом управления.

Ответ №1:

Для того, чтобы такой подход работал, вы должны сопоставить name (и id) атрибуты в вашей сгенерированной разметке с атрибутами RadioButtonList . Итак, очевидной проблемой в вашем коде является значение name атрибута — к нему следует добавить индекс для каждого переключателя, т.Е.

  ...
 sbInput.AppendFormat(
            input,
            """,
            base.ClientID   "_"   index.ToString(),
            base.UniqueID   index.ToString(),    // <<< note the change here
            base.Items[index].Value,
 ...
  

Также вместо «_» при генерации идентификатора следует использовать свойство ClientIdSeparator.

Наконец, я должен посоветовать вам отказаться от такого подхода к разработке элементов управления, потому что он по своей сути хрупкий, т. Е. он может сломаться, если произойдет изменение в том, как базовый ASP.NET элемент управления генерирует свою разметку. Например, в ASP.NET логика генерации идентификатора клиента может быть настроена, и поэтому ваша логика генерации идентификатора может работать некорректно, чтобы соответствовать исходной разметке, сгенерированной базовым элементом управления.

Комментарии:

1. Атрибуты name должны быть одинаковыми для всех кнопок radiobuttons в моем списке, потому что в противном случае я могу выбрать несколько кнопок radiobuttons, что не является целью radiobuttons.

2. @thomasvb, да — я был неправ, предлагая изменить атрибут name — я просто перепроверил и ASP.NET также генерирует атрибут с тем же именем. В таком случае, я думаю, что проблема может быть связана с генерацией идентификатора. Я предложу вам прокомментировать вашу реализацию рендеринга и посмотреть сгенерированный идентификатор для переключателя и сравнить его с тем, который сгенерирован вашей реализацией рендеринга.