鸟语天空
WPF——绑定枚举特性
post by:追风剑情 2021-9-9 14:46

示例:将枚举特性绑定到 DataGridComboBoxColumn

一、定义描述特性

[AttributeUsage(AttributeTargets.All)]
public class DescriptionAttribute : Attribute
{
	public string description;

	public DescriptionAttribute(string desc)
	{
		description = desc;
	}
}


二、定义枚举

//定义活动类型
public enum ActivityType
{
	[Description("日常")]
	Daily,      
	[Description("限时")]
	TimeLimit,  
	[Description("福利")]
	Welfare,    
	[Description("运营")]
	Business 
}


三、xaml代码片段

<!-- 活动类型 -->
<DataGridComboBoxColumn MinWidth="80" Width="80" Header="类型" >
	<!-- 非编辑模式下显示的元素 -->
	<DataGridComboBoxColumn.ElementStyle>
		<Style TargetType="ComboBox">
			<Setter Property="Text" Value="{Binding Path=ActType, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource enumTextConverter}}" />
			<Setter Property="DisplayMemberPath" Value="Text" />
			<Setter Property="SelectedItem" Value="{Binding ActType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource activityTypeConverter}}" />
			<Setter Property="ItemsSource" Value="{Binding Source={StaticResource ActivityTypeKey}}" />
		</Style>
	</DataGridComboBoxColumn.ElementStyle>
	<!-- 编辑模式下显示的元素 -->
	<DataGridComboBoxColumn.EditingElementStyle>
		<Style TargetType="ComboBox">
			<Setter Property="Text" Value="{Binding Path=ActType, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource enumTextConverter}}" />
			<Setter Property="DisplayMemberPath" Value="Text" />
			<Setter Property="SelectedItem" Value="{Binding ActType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource activityTypeConverter}}" />
			<Setter Property="ItemsSource" Value="{Binding Source={StaticResource ActivityTypeKey}}" />
		</Style>
	</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>


另一种等效的写法

<!-- 活动类型 (另一种等效的写法)-->
<DataGridTemplateColumn MinWidth="80" Width="80" Header="类型">
	<DataGridTemplateColumn.CellTemplate>
		<DataTemplate>
			<ComboBox IsEditable="False" DisplayMemberPath="Text"  Text="{Binding Path=ActType, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource enumTextConverter}}" ItemsSource="{Binding Source={StaticResource ActivityTypeKey}}" SelectedItem="{Binding ActType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource activityTypeConverter}}" />
		</DataTemplate>
	</DataGridTemplateColumn.CellTemplate>
	<DataGridTemplateColumn.CellEditingTemplate>
		<DataTemplate>
			<ComboBox IsEditable="False" DisplayMemberPath="Text"  Text="{Binding Path=ActType, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource enumTextConverter}}" ItemsSource="{Binding Source={StaticResource ActivityTypeKey}}" SelectedItem="{Binding ActType, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource activityTypeConverter}}" />
		</DataTemplate>
	</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

ActType: 要绑定的枚举变量
enumTextConverter: 枚举类型与String类型转换器
activityTypeConverter: 枚举类型与ComoBox选项数据结构之间的转换器

四、定义转换器

需要 using System.Windows.Data;

1、Enum 与 String 类型转换器

/// <summary>
/// 将枚举显示到文本框时需要用到此转换器
/// </summary>
public class EnumTextConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		Enum srcType = value as Enum;
		string text = srcType.GetDescription();
		return text;
	}

	public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
	{
		throw new NotImplementedException();
	}
}


2、ActivityType 与 ComboBoxOption 类型转换器

public class ActivityTypeConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		ActivityType srcType = (ActivityType)value;
		ComboBoxOption option = srcType.GetComboBoxOption();
		return option;
	}

	public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
	{
		ComboBoxOption dstType = (ComboBoxOption)value;
		ActivityType srcType = (ActivityType)dstType.value;
		return srcType;
	}
}


五、ComoBox下拉选项数据结构

public class ComboBoxOption
{
	public string Text { get; set; }
	public string Name { get; set; }
	public int value { get; set; }

	public new string ToString()
	{
		return Text;
	}

	public static ComboBoxOption[] GetEnumDescriptions(Type enumType)
	{
		var obj = Enum.ToObject(enumType, 0) as Enum;
		return obj.GetComboBoxOptions();
	}
}


六、添加枚举扩展方法

/// <summary>
/// Enum扩展方法
/// </summary>
internal static class EnumExtensions
{
	internal static ComboBoxOption GetComboBoxOption(this Enum e)
	{
		Type t = e.GetType();
		FieldInfo fi = t.GetField(e.ToString());
		ComboBoxOption option = new ComboBoxOption();
		option.Name = fi.Name;
		option.value = (int)fi.GetValue(null);

		object[] attributes = fi.GetCustomAttributes(true);
		if (attributes == null || attributes.Length == 0)
			return option;
		var des = attributes[0] as DescriptionAttribute;
		option.Text = des.description;
		return option;
	}

	internal static ComboBoxOption[] GetComboBoxOptions(this Enum e)
	{
		List<ComboBoxOption> optList = new List<ComboBoxOption>();
		Type t = e.GetType();
		//举中的常量都是静态的字段
		var fields = t.GetFields(BindingFlags.Static | BindingFlags.Public);
		foreach(var fi in fields)
		{
			object[] attributes = fi.GetCustomAttributes(true);
			if (attributes == null || attributes.Length == 0)
				continue;
			var des = attributes[0] as DescriptionAttribute;
			Console.WriteLine(des.description);
			ComboBoxOption option = new ComboBoxOption();
			option.Text = des.description;
			option.Name = fi.Name;
			option.value = (int)fi.GetValue(null);
			optList.Add(option);
		}
		return optList.ToArray();
	}

	internal static string GetDescription(this Enum e)
	{
		Type t = e.GetType();
		FieldInfo fi = t.GetField(e.ToString());
		object[] attributes = fi.GetCustomAttributes(true);
		if (attributes == null || attributes.Length == 0)
			return string.Empty;
		var des = attributes[0] as DescriptionAttribute;
		return des.description;
	}

	internal static string[] GetDescriptions(this Enum e)
	{
		List<string> optList = new List<string>();
		Type t = e.GetType();
		//举中的常量都是静态的字段
		var fields = t.GetFields(BindingFlags.Static | BindingFlags.Public);
		foreach (var fi in fields)
		{
			object[] attributes = fi.GetCustomAttributes(true);
			if (attributes == null || attributes.Length == 0)
				continue;
			var des = attributes[0] as DescriptionAttribute;
			Console.WriteLine(des.description);
			optList.Add(des.description);
		}
		return optList.ToArray();
	}
}


七、定义静态资源

<Application x:Class="DataEditor.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:v4="http://schemas.microsoft.com/netfx/2009/xaml/presentation"
             xmlns:core="clr-namespace:System;assembly=mscorlib"
             xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
             xmlns:local="clr-namespace:DataEditor"
             xmlns:data="clr-namespace:DataEditor.DataObject"
             xmlns:converter="clr-namespace:DataEditor.Converter"
             StartupUri="View\Windows\MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary>
            <!-- 枚举 ComoBox 静态资源 -->
            <ObjectDataProvider x:Key="ActivityTypeKey" MethodName="GetEnumDescriptions" ObjectType="{x:Type local:ComboBoxOption}">
                <ObjectDataProvider.MethodParameters>               
                    <x:Type Type="data:ActivityType" />
                </ObjectDataProvider.MethodParameters>
            </ObjectDataProvider>
			<!-- 转换器 静态资源 -->
            <data:ActivityTypeConverter x:Key="activityTypeConverter" />
            <converter:EnumTextConverter x:Key="enumTextConverter" />
        </ResourceDictionary>
    </Application.Resources>
</Application>

注意:静态资源中的代码保留了类在项目中所在的命令空间。

运行效果

111111.png

评论:
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容