WPF ComboBox与可空枚举的绑定

WPF应用程序开发中,经常需要处理各种数据绑定的场景,尤其是涉及到枚举类型的数据。当枚举类型可以为空时,就需要一种方法来处理这种情况。本文将介绍如何在WPF中使用ComboBox控件与可空枚举进行绑定,并展示相关的XAML和C#代码实现。

ViewModel的创建

首先,需要创建一个ViewModel,它将作为数据模型。在这个ViewModel中,将定义一个可空的枚举类型的属性。

using System; using System.ComponentModel; using System.Runtime.CompilerServices; namespace WpfApplication1 { public enum ProductType { [Description("湿粮")] WetFood = 1, [Description("干粮")] DryFood = 2 } public class MainWindowViewModel : INotifyPropertyChanged { private ProductType? selectedProductType; public ProductType? SelectedProductType { get { return selectedProductType; } set { selectedProductType = value; OnPropertyChanged(); } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged( [CallerMemberName] string propertyName = null) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } } }

在上面的代码中,定义了一个名为ProductType的枚举,它有两个成员:WetFood和DryFood。还定义了一个MainWindowViewModel类,它实现了INotifyPropertyChanged接口,以便在属性值发生变化时通知UI进行更新。SelectedProductType属性是一个可空的ProductType枚举类型。

XAML的编写

接下来,需要在XAML中定义UI。将使用ComboBox控件来显示枚举类型的值,并允许用户选择。

<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525"> <Window.Resources> <ObjectDataProvider x:Key="ProductTypeEnumProvider" MethodName="GetValues" ObjectType="{x:Type sys:Enum}"> <ObjectDataProvider.MethodParameters> <x:Type TypeName="local:ProductType" /> </ObjectDataProvider.MethodParameters> </ObjectDataProvider> </Window.Resources> <Grid> <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center" SelectedItem="{Binding SelectedProductType, Converter={x:Static local:NullableEnumConverter.Instance}, ConverterParameter={x:Static local:ProductType.DryFood}}"> <ComboBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Path=., Mode=OneWay, Converter={x:Static local:NullableEnumToFriendlyNameConverter.Instance}}" Height="Auto" Margin="0" VerticalAlignment="Center" /> </DataTemplate> </ComboBox.ItemTemplate> <ComboBox.ItemsSource> <CompositeCollection> <x:Static Member="local:NullHelper.NullComboStringValue" /> <CollectionContainer Collection="{Binding Source={StaticResource ProductTypeEnumProvider}}" /> </CompositeCollection> </ComboBox.ItemsSource> </ComboBox> </Grid> </Window>

在上面的XAML代码中,定义了一个ComboBox控件,并使用了一个ObjectDataProvider来获取枚举类型的所有值。还定义了一个ItemTemplate,用于显示每个枚举值的友好名称。ComboBox的ItemsSource属性被设置为一个CompositeCollection,它允许将不同的数据源组合在一起。

辅助类和值转换器

为了使ComboBox能够正确显示枚举值的友好名称,需要定义一些辅助类和值转换器。

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace WpfApplication1 { public class NullHelper { public static string NullComboStringValue { get { return "无"; } } } }

NullHelper类提供了一个静态属性NullComboStringValue,它返回一个字符串"无",用于表示ComboBox中的空选项。

using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Windows.Data; namespace WpfApplication1 { public class NullableEnumConverter : IValueConverter { private NullableEnumConverter() { } static NullableEnumConverter() { Instance = new NullableEnumConverter(); } public static NullableEnumConverter Instance { get; private set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value == null) { return NullHelper.NullComboStringValue; } return value; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { Type enumType = parameter.GetType(); if (value.ToString().Equals(NullHelper.NullComboStringValue)) { return null; } object rawEnum = Enum.Parse(enumType, value.ToString()); return System.Convert.ChangeType(rawEnum, enumType); } } }

NullableEnumConverter类实现了IValueConverter接口,用于将可空枚举值转换为友好名称。如果枚举值为空,则返回NullHelper类中定义的字符串。

using System; using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reflection; using System.Windows.Data; namespace WpfApplication1 { [ValueConversion(typeof(object), typeof(String))] public class NullableEnumToFriendlyNameConverter : IValueConverter { private NullableEnumToFriendlyNameConverter() { } static NullableEnumToFriendlyNameConverter() { Instance = new NullableEnumToFriendlyNameConverter(); } public static NullableEnumToFriendlyNameConverter Instance { get; private set; } public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if (value != null && !string.IsNullOrEmpty(value.ToString()) && !value.ToString().Equals(NullHelper.NullComboStringValue)) { FieldInfo fi = value.GetType().GetField(value.ToString()); if (fi != null) { var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false); return ((attributes.Length > 0) && (!String.IsNullOrEmpty(attributes[0].Description))) ? attributes[0].Description : value.ToString(); } } return NullHelper.NullComboStringValue; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new Exception("Can't convert back"); } } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485