WPF MVVM在ItemsControl上使用单选按钮
WPF MVVM在ItemsControl上使用单选按钮
我之前曾将枚举绑定到单选按钮上,并且大体上了解它的工作原理。我使用了这个问题的备选实现:如何将单选按钮与枚举绑定?
与枚举不同,我想要在运行时生成一组用于自定义类型的运行时枚举,并将它们呈现为一组单选按钮。我已经在运行时枚举的集合上使用了一个 ListView
视图,并绑定了 ItemsSource
和 SelectedItem
属性,所以我的 ViewModel
已经正确连接。现在我正在尝试从 ListView
切换到带有单选按钮的 ItemsControl
。
这是我到了那里:
InstanceToBooleanConverter
的实现与那个问题中的 EnumToBooleanConverter
是相同的。这看起来没错,因为它似乎只是调用 Equals
方法:
public class InstanceToBooleanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(parameter); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return value.Equals(true) ? parameter : Binding.DoNothing; } }
我现在遇到的问题是,我不知道如何将运行时值作为 ConverterParameter
发送。当我尝试(使用上面的代码)时,我会收到以下错误:
不能在类型为“绑定”的“ConverterParameter”属性上设置“绑定”。只能在 DependencyObject 的 DependencyProperty 上设置“绑定”。
是否有一种方法可以绑定到项实例,并将其传递给 IValueConverter
?
据我所知,使用MultiBinding
没有好的方式可以实现这个操作,即使最初你认为有可能。因为你无法绑定ConverterParameter
,因此你的ConvertBack
实现没有所需的信息。\n\n我所做的是创建一个专门用于将枚举绑定到单选按钮的EnumModel
类。在ItemsSource
属性上使用转换器,然后你就可以将其绑定到EnumModel
上了。EnumModel
只是一个转接对象,使得绑定成为可能。它持有枚举的一个可能值以及对视图模型的引用,因此它可以将视图模型上的属性从布尔值翻译为对应的枚举值,反之亦然。\n\n下面是一个未经测试但通用的版本:
。\n\n转换器:
public class ToEnumModelsConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { var viewmodel = value; var prop = viewmodel.GetType().GetProperty(parameter as string); ListenumModels = new List (); foreach(var enumValue in Enum.GetValues(prop.PropertyType)) { var enumModel = new EnumModel(enumValue, viewmodel, prop); enumModels.Add(enumModel); } return enumModels; } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } }
。\n\nEnumModel
:
public class EnumModel : INPC { object enumValue; INotifyPropertyChanged viewmodel; PropertyInfo property; public EnumModel(object enumValue, object viewmodel, PropertyInfo property) { this.enumValue = enumValue; this.viewmodel = viewmodel as INotifyPropertyChanged; this.property = property; this.viewmodel.PropertyChanged += new PropertyChangedEventHandler(viewmodel_PropertyChanged); } void viewmodel_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == property.Name) { OnPropertyChanged("IsChecked"); } } public bool IsChecked { get { return property.GetValue(viewmodel, null).Equals(enumValue); } set { if (value) { property.SetValue(viewmodel, enumValue, null); } } } }
。\n\n为了演示一个我知道可用的代码示例(但仍然相当不成熟——仍在进行中!),你可以访问http://code.google.com/p/pdx/source/browse/trunk/PDX/PDX/Toolkit/EnumControl.xaml.cs。这仅适用于我的库的上下文环境,但它演示了基于DescriptionAttribute
设置EnumModel
的名称,这对你可能有用。