问题描述
一个类由一个枚举和一个转换器组成,该转换器的工作是将枚举值转换为几何。可以在下面看到:
public enum GeometryEnum
{
Triangle,Rectangle,RoundedRectangle,Diamond,Pentagonal,Hexagonal,Heptagonal,Octagonal,Decagonal,Ellipse,Star5,Star6,Star7,Star8,Star10
}
public class EnumToGeometryConverter : IValueConverter
{
public object Convert(object value,Type targettype,object parameter,CultureInfo culture)
{
GeometryEnum _enumGeometry;
if (value != null)
_enumGeometry = (GeometryEnum)Enum.Parse(typeof(GeometryEnum),value.ToString());
else if (parameter != null)
_enumGeometry = (GeometryEnum)Enum.Parse(typeof(GeometryEnum),parameter.ToString());
else
return null;
switch (_enumGeometry)
{
case GeometryEnum.Triangle: return Geometry.Parse("M0.5,0 1,1 0,1 Z");
case GeometryEnum.Ellipse: return new EllipseGeometry(new System.Windows.Point(0.5,0.5),0.5,0.5);
case GeometryEnum.Rectangle: return new RectangleGeometry(new System.Windows.Rect(new System.Windows.Size(1,1)));
case GeometryEnum.RoundedRectangle: return new RectangleGeometry(new System.Windows.Rect(new System.Windows.Size(1,1)),0.1d,0.1d);
}
return null;
}
public object ConvertBack(object value,CultureInfo culture)
{
return null;
}
}
我想使用此转换器将每个枚举值转换为其等效的几何形状。我在程序的其他部分使用此转换没有任何问题。 但是当我在菜单项的Icon属性中使用它时,我看到只有最后一个菜单项具有Icon,其他菜单项都为空。
<ObjectDataProvider x:Key="DataGeometryTypeEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="classes:GeometryEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<MenuItem Header="Shape Type" Command="{x:Static tndcontrols:TndGraphCanvas.ComboBoxShapeRoutedCommand}"
ItemsSource="{Binding Source={StaticResource DataGeometryTypeEnum}}"
>
<MenuItem.ItemContainerStyle>
<Style targettype="{x:Type MenuItem}">
<Setter Property="Command" Value="{x:Static tndcontrols:TndGraphCanvas.ComboBoxShapeRoutedCommand}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="Icon">
<Setter.Value>
<Image Width="16" Height="16">
<Image.source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280" Geometry="{Binding Converter={StaticResource EnumToGeometryConverter}}">
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.source>
</Image>
</Setter.Value>
</Setter>
</Style>
</MenuItem.ItemContainerStyle>
<MenuItem.Icon>
<Image Source="Images/Icons/Shapes.ico" Width="16" Height="16"/>
</MenuItem.Icon>
</MenuItem>
解决方法
我经常使用字典转换器。 它提供了各种值的通用转换。 我认为这将适合您解决问题:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
namespace Common
{
/// <summary>A converter that converts a key to a dictionary value.</summary>
public class DictionaryKeyToValueConverter : Dictionary<object,object>,IMultiValueConverter,IValueConverter
{
// The first element in the values parameter comes the key,the second - the dictionary.
public object Convert(object[] values,Type targetType,object parameter,CultureInfo culture)
{
// If only the key is received,the converter dictionary is used.
if (values.Length == 1)
{
if (TryGetValue(values[0],out object val))
return val;
}
// If more than one element came,then the key is extracted from the first,and the dictionary from the second.
else if (values.Length > 1 && (values[1] is IDictionary dictionary) && (dictionary.Contains(values[0])))
{
return dictionary[values[0]];
}
return null;
}
// The dictionary key should come in the value parameter.
public object Convert(object value,CultureInfo culture)
{
if (TryGetValue(value,out object val))
return val;
return null;
}
public object[] ConvertBack(object value,Type[] targetTypes,CultureInfo culture)
{
throw new NotImplementedException();
}
public object ConvertBack(object value,CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
示例:
<Window x:Class="IconsMenu.IconMenuWind"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:IconsMenu"
xmlns:System="clr-namespace:System;assembly=mscorlib" xmlns:comm="clr-namespace:Common"
mc:Ignorable="d"
Title="IconMenuWind" Height="450" Width="800">
<Window.Resources>
<ObjectDataProvider x:Key="DataGeometryTypeEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:GeometryEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<comm:DictionaryKeyToValueConverter x:Key="EnumToImageConverter">
<DrawingImage x:Key="{x:Static local:GeometryEnum.Triangle}">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280" Geometry="M 0.5 0 1,1 0,1 Z">
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="{x:Static local:GeometryEnum.Ellipse}">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280">
<GeometryDrawing.Geometry>
<EllipseGeometry Center="0.5 0.5" RadiusX="0.5" RadiusY="0.5"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="{x:Static local:GeometryEnum.Rectangle}">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,1,1"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
<DrawingImage x:Key="{x:Static local:GeometryEnum.RoundedRectangle}">
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,1" RadiusX="0.1" RadiusY="0.1"/>
</GeometryDrawing.Geometry>
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</comm:DictionaryKeyToValueConverter>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Mode=OneWay,Source={StaticResource DataGeometryTypeEnum}}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualHeight,ElementName=grid,Mode=OneWay}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image Source="{Binding Converter={StaticResource EnumToImageConverter},Mode=OneWay}"/>
<TextBlock Text="{Binding}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
或者像这样:
<Window.Resources>
<ObjectDataProvider x:Key="DataGeometryTypeEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:GeometryEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<comm:DictionaryKeyToValueConverter x:Key="EnumToImageConverter">
<Geometry x:Key="{x:Static local:GeometryEnum.Triangle}">M 0.5 0 1,1 Z</Geometry>
<EllipseGeometry x:Key="{x:Static local:GeometryEnum.Ellipse}" Center="0.5 0.5" RadiusX="0.5" RadiusY="0.5"/>
<RectangleGeometry x:Key="{x:Static local:GeometryEnum.Rectangle}" Rect="0,1"/>
<RectangleGeometry x:Key="{x:Static local:GeometryEnum.RoundedRectangle}" Rect="0,1" RadiusX="0.1" RadiusY="0.1"/>
</comm:DictionaryKeyToValueConverter>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Mode=OneWay,Source={StaticResource DataGeometryTypeEnum}}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualHeight,Mode=OneWay}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280" Geometry="{Binding Converter={StaticResource EnumToImageConverter},Mode=OneWay}" >
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="#FF212121"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock Text="{Binding}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
使用多个转换器实例与多个枚举一起使用的示例。
添加的枚举:
public enum ColorsEnum
{
Black,Green
}
XAML:
<Window.Resources>
<ObjectDataProvider x:Key="DataGeometryTypeEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:GeometryEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="DataColorsTypeEnum" MethodName="GetValues"
ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:ColorsEnum"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<comm:DictionaryKeyToValueConverter x:Key="DictionaryConverter">
<Geometry x:Key="{x:Static local:GeometryEnum.Triangle}">M 0.5 0 1,1" RadiusX="0.1" RadiusY="0.1"/>
<SolidColorBrush x:Key="{x:Static local:ColorsEnum.Black}" Color="Black"/>
<SolidColorBrush x:Key="{x:Static local:ColorsEnum.Green}" Color="Green"/>
</comm:DictionaryKeyToValueConverter>
<comm:DictionaryKeyToValueConverter x:Key="ForegroundConverter">
<SolidColorBrush x:Key="{x:Static local:GeometryEnum.Triangle}" Color="Gray" />
<SolidColorBrush x:Key="{x:Static local:GeometryEnum.Ellipse}" Color="Green"/>
<SolidColorBrush x:Key="{x:Static local:GeometryEnum.Rectangle}" Color="Blue"/>
<SolidColorBrush x:Key="{x:Static local:GeometryEnum.RoundedRectangle}" Color="Coral"/>
<SolidColorBrush x:Key="{x:Static local:ColorsEnum.Black}" Color="LightGray"/>
<SolidColorBrush x:Key="{x:Static local:ColorsEnum.Green}" Color="Yellow"/>
</comm:DictionaryKeyToValueConverter>
</Window.Resources>
<Grid>
<ListBox ItemsSource="{Binding Mode=OneWay,Source={StaticResource DataGeometryTypeEnum}}"
HorizontalAlignment="Left">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding ActualHeight,Mode=OneWay}"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Image>
<Image.Source>
<DrawingImage>
<DrawingImage.Drawing>
<GeometryDrawing Brush="#FF466280"
Geometry="{Binding Converter={StaticResource DictionaryConverter},Mode=OneWay}" >
<GeometryDrawing.Pen>
<Pen Thickness="1" Brush="{Binding Converter={StaticResource ForegroundConverter}}"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingImage.Drawing>
</DrawingImage>
</Image.Source>
</Image>
<TextBlock Text="{Binding}" Grid.Column="1"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Mode=OneWay,Source={StaticResource DataColorsTypeEnum}}" HorizontalAlignment="Center">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
Background="{Binding Converter={StaticResource DictionaryConverter}}"
Foreground="{Binding Converter={StaticResource ForegroundConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ListBox ItemsSource="{Binding Keys,Source={StaticResource DictionaryConverter}}" HorizontalAlignment="Right"/>
</Grid>