Является ли пользовательский `RadioButtonList` основанным на` ListBox` необходимым в WPF?

Я унаследовал проект, который использует RadioButtonList, который наследует от ListBox. Он был снят с Интернета (в настоящее время он не может найти ссылку) и содержит RadioButtonList.cs(который содержит шесть свойств зависимостей) и RadioButtonList.xaml(это только стили и шаблоны управления).

Этот элемент управления используется в более чем ста местах. Это вызывает проблемы, потому что это не полный и профессиональный контроль. Такие проблемы, как проблемы с фокусом, клавиатура и т.д. (См. Комментарии.)

После долгих исследований в разное время за последние пару лет кажется, что этот контроль действительно не нужен. Все, что нужно, - установить свойство GroupName в группе радиокнопки. И единственная причина, по которой используется элемент управления RadioButtonList, - это помочь с привязкой данных к списку опций через наследуемый ListBox.

1) Действительно ли этот контроль необходим? Есть ли лучший способ?

2) Есть ли профессиональный контроль, open-source или иное, что позволит мне получить преимущества привязки данных без головных болей? (Мы используем Infragistics и DevExpress, но я не знаком со всеми элементами управления, предлагаемыми этими наборами.)

Мои ответы

1a) Действительно ли этот контроль необходим?

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

1b) Есть ли лучший способ?

  • Я говорю, что вывод из ListBox, ItemsControl или что-то другое, создавая стили и шаблоны, - единственный способ создать этот элемент управления; поэтому нет лучшего способа.

2) Есть ли профессиональный контроль...

  • Определенно, ListBoxEdit с RadioListBoxEditStyleSettings.

Комментарии относительно ответов

Все ответы указывают, что создание элемента управления RadioButtonList не требуется. Тем не менее, если вам нужно больше, чем несколько списков радиокнопок, к моменту создания стилей и шаблонов управления и, возможно, шаблона данных вы получите коллекцию артефактов кода, которую можно назвать радиокнопочным списком, контроль. Поэтому, на мой взгляд, необходим a RadioButtonList.

Кроме того, мое понимание - это RadioButtonList, было сброшено в раннем WPF CTP. Что я могу понять из-за ограниченной потребности в таком контроле, который можно легко создать.

Комментарий относительно принятого ответа

2) Есть ли профессиональный контроль...

  • Определенно, ListBoxEdit с RadioListBoxEditStyleSettings.

Последний комментарий к Mike Strobel Отвечать

RadioButtonList, который у меня есть, является конечным результатом его ответа. Хотя я хорош в создании пользовательских элементов управления, я предпочитаю, чтобы сторонние производители компонентов, такие как Infragistics и DevExpress, создавали и поддерживали базовый элемент управления, подобный этому.

Ответ 1

Я могу только сказать вам, что DevExpress использует ListBoxEdit с RadioListBoxEditStyleSettings для представления группы RadioButtons. Практически это то же самое, что и ваш контроль, который вы используете, но я думаю, что он обеспечивает лучшую функциональность и хорошо тестируется. RadioButton не предоставляется DevExpress, и в моем приложении я использую Default RadionButton-Control, предоставляемый WPF/Silverlight.

Вы используете RadioListBoxEdit для DevExpress следующим образом:

<dxe:ListBoxEdit SelectedItem={Binding CheckItem, Mode=TwoWay}>
  <dxe:ListBoxEdit.StyleSettings>
    <dxe:RadioListBoxEditStyleSettings />
  </dxe:ListBoxEdit.StyleSettings>
</dxe:ListBoxEdit>

Более подробную информацию о ListBoxEdit из DevExpress можно найти здесь

Ответ 2

Действительно ли этот контроль необходим? Есть ли лучший способ?

Как указывает @lawc, нет, это необязательно. Однако это может быть предпочтительным, в зависимости от того, какой уровень гибкости вы желаете. Многоразовый стиль достаточно прост для создания, но выполнение его "правильно" немного более активно, чем просто настройка пользовательского ItemTemplate.

Использование стилей

An ItemsControl в WPF переносит свои элементы в соответствующие контейнеры. Каждый из элементов управления селектора в основном WPF переопределяет логику, которая определяет, может ли элемент служить в качестве своего собственного контейнера, а также код factory, который создает контейнеры для новых элементов. Например, ListBox будет обертывать каждый из своих элементов в ListBoxItem (если сам элемент уже не является ListBoxItem). Стиль, применяемый к этим контейнерам, может быть установлен для родительского ItemsControl через свойство ItemContainerStyle. Это отличается от свойства ItemTemplate, что позволяет вам контролировать внешний вид элемента в контейнере. Более конкретно, он переопределяет шаблон содержимого, примененный к ContentPresenter внутри контейнера.

Так как a RadioButton не получается из ListBoxItem, просто установка ItemTemplate приведет к созданию списка элементов управления RadioButton, встроенных в элементы управления ListBoxItem, что означает, что они все равно будут иметь тот же самый хром, который обычно ассоциируется с элементами управления ListBox и, возможно, некоторыми макетами и фокусными странностями. Вероятно, это не то, что вы хотите.

Вместо этого переопределите ItemContainerStyle и используйте его для назначения пользовательского шаблона ListBoxItem, который вставляет RadioButton. Вероятно, вам удастся избежать установки свойства GroupName, что устраняет возможные столкновения имен. Вместо этого просто установите двустороннюю привязку между свойством RadioButton.IsChecked и шаблоном родительским свойством ListBoxItem.IsSelected.

Чтобы использовать эту технику удобно, обычно создается ресурс Style (доступный в масштабе всего приложения), который может быть применен к соответствующим экземплярам ListBox, и который устанавливает ItemContainerStyle. Кроме того, вы можете сделать стиль контейнера доступным как глобальный ресурс и установить его в своих экземплярах ListBox. В любом случае вам нужно установить свойство.

Использование пользовательского элемента управления

В то время как евангелисты WPF часто повторяют философию предпочтения пользовательских стилей над пользовательскими элементами управления, на практике это не всегда удобно. Возможно, вам будет удобнее создавать RadioButtonList, который расширяет элемент управления ListBox, а затем дает ему стиль по умолчанию, который автоматически применяет пользовательский стиль, описанный выше. Это избавит вас от необходимости вручную назначать стиль списка или стиль контейнера на каждом экземпляре ListBox, но это не огромная победа.

Но, возможно, вам нужно немного больше контролировать внешний вид элементов RadioButton. Например, вы можете:

  • Отрегулируйте маржу вокруг "пули" каждого элемента RadioButton;
  • Отрегулируйте вертикальное выравнивание маркеров относительно содержимого;
  • Поддержка горизонтальной и вертикальной ориентации;
  • Автоматически отключать содержимое RadioButton для элементов, которые не выбраны.

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

Сторонние решения

Есть ли профессиональный контроль, с открытым исходным кодом или иным образом, который позволит мне получить преимущества привязки данных без головных болей?

Это не необычный случай использования, и я не сомневаюсь, что вокруг него есть некоторые реализации. Некоторые из них могут быть в фреймворках с открытым исходным кодом, а некоторые из них могут быть извлечены из приложений с открытым исходным кодом. Что касается сторонних реализаций, я знаю, что Actipro отправляет RadioButtonList в свою общую библиотеку WPF, которая включена во все их компонентов WPF. Когда последний раз я проверял, он был недоступен сам по себе. Тем не менее, он поддерживает все дополнительные функции, перечисленные выше.

Ответ 3

По-моему, вам не нужен этот контроль. Вы можете просто использовать .Net ListBox для достижения всех существующих функций.

  • Используя ListBox.ItemsSource, вы можете привязать данные к вашей коллекции опций
  • Укажите ListBox.ItemTemplate, содержащий RadioButton, в этом шаблоне вы можете привязать ваше свойство модели просмотра к RadioButton.GroupName

Ответ 4

IMHO, контроль, полученный из ItemsControl, был бы самым чистым подходом.

Тогда вы, вероятно, переопределите

  • IsItemItsOwnContainerOverride() с return item is RadioButton;
  • GetContainerForItemOverride() до return a new RadioButton() для каждого элемента и
  • PrepareContainerForItemOverride(), чтобы установить привязку ToggleButton.IsCheckedProperty и ContentControl.ContentProperty.

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