我正在我正在使用的应用程序中使用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
}
答案 0 :(得分:7)
创建一个公开字符串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);
}