I have a ComboBox
for which I bound ItemsSource
to a enum collection and SelectedItem
to a DependencyProperty
of the same enum type. So far no problem.
Now I want to display a drawing (associated with each value of the enum collection) instead of the text.
My idea is to use a Converter to translate the value to drawing (and viceversa), using the resource Tag.
in MainWindow.xaml
<Window
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:System="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfApp1"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
x:Class="WpfApp1.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="200">
<Window.Resources>
<ObjectDataProvider x:Key="Letters" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Letters"/>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<local:LetterConverter x:Key="LetterConverter"/>
</Window.Resources>
<Grid>
<ComboBox x:Name="Letter" Grid.Row="0" Width="48" Height="32" ItemsSource="{Binding Source={StaticResource Letters}}" SelectedItem="{Binding Path=SelectedLetter}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Viewbox Stretch="Uniform" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border>
<ContentPresenter Content="{Binding Converter={StaticResource LetterConverter}}"/>
</Border>
</Viewbox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</Grid>
</Window>
in MainWindow.cs
using System;
using System.Windows;
using System.Windows.Data;
namespace WpfApp1
{
/// <summary>
/// Logica di interazione per MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region SelectedLetter property
public Letters SelectedLetter
{
get { return (Letters)GetValue(SelectedLetterProperty); }
set { SetValue(SelectedLetterProperty, value); }
}
public static readonly DependencyProperty SelectedLetterProperty =
DependencyProperty.Register("SelectedLetter", typeof(Letters), typeof(MainWindow), new PropertyMetadata(Letters.E, new PropertyChangedCallback(LetterChanged)));
private static void LetterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MainWindow instance = d as MainWindow;
MessageBox.Show(e.NewValue.ToString());
}
#endregion
public MainWindow()
{
InitializeComponent();
}
}
public enum Letters
{
A, B, C, D, E
}
[ValueConversion(typeof(Letters), typeof(FrameworkElement))]
public class LetterConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
switch ((Letters)value)
{
case Letters.A:
return (FrameworkElement)Application.Current.Resources["A"];
case Letters.B:
return (FrameworkElement)Application.Current.Resources["B"];
case Letters.C:
return (FrameworkElement)Application.Current.Resources["C"];
case Letters.D:
return (FrameworkElement)Application.Current.Resources["D"];
case Letters.E:
return (FrameworkElement)Application.Current.Resources["E"];
default:
throw new ArgumentOutOfRangeException();
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (((FrameworkElement)value).Tag.ToString().Equals("A"))
return Letters.A;
if (((FrameworkElement)value).Tag.ToString().Equals("B"))
return Letters.B;
if (((FrameworkElement)value).Tag.ToString().Equals("C"))
return Letters.C;
if (((FrameworkElement)value).Tag.ToString().Equals("D"))
return Letters.D;
if (((FrameworkElement)value).Tag.ToString().Equals("E"))
return Letters.E;
throw new ArgumentOutOfRangeException();
}
}
}
in App.xaml
<Application x:Class="WpfApp1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Canvas x:Key="A" Width="24" Height="24" Tag="A">
<Path Width="24" Height="24" Data="M11,7H13A2,2 0 0,1 15,9V17H13V13H11V17H9V9A2,2 0 0,1 11,7M11,9V11H13V9H11M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="B" Width="24" Height="24" Tag="B">
<Path Width="24" Height="24" Data="M15,10.5C15,11.3 14.3,12 13.5,12C14.3,12 15,12.7 15,13.5V15A2,2 0 0,1 13,17H9V7H13A2,2 0 0,1 15,9V10.5M13,15V13H11V15H13M13,11V9H11V11H13M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="C" Width="24" Height="24" Tag="C">
<Path Width="24" Height="24" Data="M11,7H13A2,2 0 0,1 15,9V10H13V9H11V15H13V14H15V15A2,2 0 0,1 13,17H11A2,2 0 0,1 9,15V9A2,2 0 0,1 11,7M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="D" Width="24" Height="24" Tag="D">
<Path Width="24" Height="24" Data="M9,7H13A2,2 0 0,1 15,9V15A2,2 0 0,1 13,17H9V7M11,9V15H13V9H11M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="E" Width="24" Height="24" Tag="E">
<Path Width="24" Height="24" Data="M9,7H15V9H11V11H15V13H11V15H15V17H9V7M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
</Application.Resources>
</Application>
At this point, once an element is selected from the drop-list, it becomes smaller and is no longer visible.
Any suggestions?
Set the x:Shared attribute of your resources to false:
<Canvas x:Key="A" Width="24" Height="24" Tag="A" x:Shared="False">
<Path Width="24" Height="24" Data="M11,7H13A2,2 0 0,1 15,9V17H13V13H11V17H9V9A2,2 0 0,1 11,7M11,9V11H13V9H11M12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="B" Width="24" Height="24" Tag="B" x:Shared="False">
<Path Width="24" Height="24" Data="M15,10.5C15,11.3 14.3,12 13.5,12C14.3,12 15,12.7 15,13.5V15A2,2 0 0,1 13,17H9V7H13A2,2 0 0,1 15,9V10.5M13,15V13H11V15H13M13,11V9H11V11H13M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="C" Width="24" Height="24" Tag="C" x:Shared="False">
<Path Width="24" Height="24" Data="M11,7H13A2,2 0 0,1 15,9V10H13V9H11V15H13V14H15V15A2,2 0 0,1 13,17H11A2,2 0 0,1 9,15V9A2,2 0 0,1 11,7M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="D" Width="24" Height="24" Tag="D" x:Shared="False">
<Path Width="24" Height="24" Data="M9,7H13A2,2 0 0,1 15,9V15A2,2 0 0,1 13,17H9V7M11,9V15H13V9H11M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
<Canvas x:Key="E" Width="24" Height="24" Tag="E" x:Shared="False">
<Path Width="24" Height="24" Data="M9,7H15V9H11V11H15V13H11V15H15V17H9V7M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2M12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12A8,8 0 0,0 12,4Z" Fill="Black"/>
</Canvas>
If you don't, the same Canvas
element is reused and a visual element can only appear once in the visual tree.