[英]How to bind to radio buttons created dynamically in WPF?
我在我正在使用的应用程序中使用WPF和MVVM。
我正在动态创建5个单选按钮,在创建时我使用枚举和IValueConverter设置绑定。
这没关系,因为我知道我只需要5个单选按钮,但现在我需要创建的单选按钮的数量可以改变,它们可以是5,因为它们可能是30。
那么,这是将单选按钮与代码绑定的最佳方法? 我想我不能再使用枚举了,除非我设法动态创建枚举,我不知道是否有可能我读到有关动态枚举的内容......
谢谢。
编辑
这里或多或少是我用来动态创建单选按钮的代码。
public enum MappingOptions {
Option0,
Option1,
Option2,
Option3,
Option4
}
private MappingOptions mappingProperty;
public MappingOptions MappingProperty
{
get { return mappingProperty; }
set
{
mappingProperty= value;
base.RaisePropertyChanged("MappingProperty");
}
}
private void CreateRadioButtons()
{
int limit = 5;
int count = 0;
string groupName = "groupName";
parent.FormWithRadioButtons.Children.Clear();
foreach (CustomValue value in AllCustomValues)
{
if (count < limit)
{
System.Windows.Controls.RadioButton tmpRadioBtn = new System.Windows.Controls.RadioButton();
tmpRadioBtn.DataContext = this;
tmpRadioBtn.Content = value.Name;
tmpRadioBtn.GroupName = groupName;
tmpRadioBtn.Margin = new System.Windows.Thickness(10, 0, 0, 5);
string parameter = string.format("Option{0}", count.ToString());
System.Windows.Data.Binding tmpBinding = new System.Windows.Data.Binding("MappingProperty");
tmpBinding.Converter = new EnumBooleanConverter();
tmpBinding.ConverterParameter = parameter;
tmpBinding.Source = this;
try
{
tmpRadioBtn.SetBinding(System.Windows.Controls.RadioButton.IsCheckedProperty, tmpBinding);
}
catch (Exception ex)
{
//handle exeption
}
parent.FormWithRadioButtons.Children.Add(tmpRadioBtn);
count += 1;
}
else
break;
}
MappingProperty = MappingOptions.Option0;
}
public class EnumBooleanConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string parameterString = parameter as string;
if (parameterString == null)
return System.Windows.DependencyProperty.UnsetValue;
if (Enum.IsDefined(value.GetType(), value) == false)
return System.Windows.DependencyProperty.UnsetValue;
object parameterValue = Enum.Parse(value.GetType(), parameterString);
return parameterValue.Equals(value);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string parameterString = parameter as string;
if (parameterString == null)
return System.Windows.DependencyProperty.UnsetValue;
return Enum.Parse(targetType, parameterString);
}
#endregion
}
创建一个公开字符串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; }
}
创建一个项目,添加这些类,将ItemsControl
XAML粘贴到主窗口的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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.