Создайте класс, который предоставляет строковые Text
и логические IsChecked
свойства и который реализует INotifyPropertyChanged
. Назовите это, о, MutexViewModel
.
Создайте другой класс, который реализует наблюдаемую коллекцию этих объектов с именем Mutexes
, и который обрабатывает PropertyChanged
для каждого - например, имеет конструктор вроде:
public MutexesViewModel(IEnumerable<MutexViewModel> mutexes)
{
_Mutexes = new ObservableCollection<MutexViewModel>();
foreach (MutexViewModel m in Mutexes)
{
_Mutexes.Add(m);
m.PropertyChanged += MutexViewModel_PropertyChanged;
}
}
и обработчик событий, который гарантирует, что только один из дочерних объектов имеет IsChecked
, установленный в true в любой момент времени:
private void MutexViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MutexViewModel m = (MutexViewModel)sender;
if (e.PropertyName != "IsChecked" || !m.IsChecked)
{
return;
}
foreach (MutexViewModel other in _Mutexes.Where(x: x != m))
{
other.IsChecked = false;
}
}
Теперь у вас есть механизм для создания произвольного числа именованных логических свойств, которые являются взаимоисключающими, то есть только одно из них может быть истинным в любой момент времени.
Теперь создайте XAML следующим образом - DataContext
для этого объекта является MutexesViewModel
, но вы также можете связать ItemsSource
с чем-то вроде {DynamicResource myMutexesViewModel.Mutexes}
.
<ItemsControl ItemsSource="{Binding Mutexes}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="local:MutexViewModel">
<RadioButton Content="{Binding Text}" IsChecked="{Binding IsChecked, Mode=TwoWay}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Редактировать
В XAML, который я опубликовал, была синтаксическая ошибка, но ничего, что могло бы вас остановить. Эти занятия работают:
public class MutexViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Text { get; set; }
private bool _IsChecked;
public bool IsChecked
{
get { return _IsChecked; }
set
{
if (value != _IsChecked)
{
_IsChecked = value;
OnPropertyChanged("IsChecked");
}
}
}
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler h = PropertyChanged;
if (h != null)
{
h(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class MutexesViewModel
{
public MutexesViewModel(IEnumerable<MutexViewModel>mutexes)
{
Mutexes = new ObservableCollection<MutexViewModel>(mutexes);
foreach (var m in Mutexes)
{
m.PropertyChanged += MutexViewModel_PropertyChanged;
}
}
private void MutexViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
MutexViewModel m = (MutexViewModel) sender;
if (e.PropertyName == "IsChecked" && m.IsChecked)
{
foreach(var other in Mutexes.Where(x => x != m))
{
other.IsChecked = false;
}
}
}
public ObservableCollection<MutexViewModel> Mutexes { get; set; }
}
Создайте проект, добавьте эти классы, вставьте XAML ItemsControl
в XAML главного окна и добавьте его в код основного окна:
public enum Test
{
Foo,
Bar,
Baz,
Bat
} ;
public MainWindow()
{
InitializeComponent();
var mutexes = Enumerable.Range(0, 4)
.Select(x => new MutexViewModel
{ Text = Enum.GetName(typeof (Test), x) });
DataContext = new MutexesViewModel(mutexes);
}