wpfcomboboxselecteditemivalueconverteritemsource

Why ComboBox item shrinks in the DropDownBorder after it is selected?


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?


Solution

  • 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.