It is pretty simple.
A path is a WPF object, and therefore each WPF object can have only one parent object. When a WPF object has a parent set, it cannot be used in another parent.
What happens is that the DataTemplate is loaded and it shows your items. You select one element with Path, and it is set in the selected ContentPresenter element of your Combobox (it should be shown). This separates the path from your original object, causing your elements to “disappear”. Your objects are still present, but you cannot see them because it no longer has a visible object, since the path has been removed from your original list. In the case of a string, this works because the string is not a WPF object.
Hope this makes it a little easier.
So now for the solution:
If you want to save the green text as text, you can do the following:
Make your ColorList of type Color enum:
public class ColorList : List<Color> { }
Throw a few things:
public partial class Window1 : Window { public Window1() { this.Resources["ColorList"] = new[] { Color.Red, Color.Blue, Color.Green }; InitializeComponent(); } private Color _activeColor; public Color ActiveColor { get { return _activeColor; } set { _activeColor = value; } } } public class ColorList : List<Color> { } public enum Color { Red, Blue, Green }
And expand your DataTemplate to set a specific data pattern for Red and Blue using Trigger objects in the DataTemplate:
<Window x:Class="WpfApplication6.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:WpfApplication6="clr-namespace:WpfApplication6" Title="ComboBoxTest" Height="100" Width="200"> <ComboBox ItemsSource="{Binding Source={StaticResource ColorList}}" SelectedItem="{Binding ActiveColor, ElementName=ComboBoxTest}"> <ComboBox.ItemTemplate> <DataTemplate> <ContentControl Content="{Binding}" x:Name="content" /> <DataTemplate.Triggers> <DataTrigger Binding="{Binding}" Value="{x:Static WpfApplication6:Color.Red}"> <Setter TargetName="content" Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Red"/> </DataTemplate> </Setter.Value> </Setter> </DataTrigger> <DataTrigger Binding="{Binding}" Value="{x:Static WpfApplication6:Color.Blue}"> <Setter TargetName="content" Property="ContentTemplate"> <Setter.Value> <DataTemplate> <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="Blue"/> </DataTemplate> </Setter.Value> </Setter> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox> </Window>
Clean approach:
If you want all the elements to be colored objects, you will need a converter object to convert the color value of the color to the color you want to show:
<ComboBox ItemsSource="{Binding Source={StaticResource ColorList}}" SelectedItem="{Binding ActiveColor, ElementName=ComboBoxTest}"> <ComboBox.ItemTemplate> <DataTemplate> <Path Data="M0,0 L0,30 60,30 60,0 Z" Fill="{Binding Converter={StaticResource ColorConverter}}"/> </DataTemplate> </ComboBox.ItemTemplate> </ComboBox>
And a good converter that you need to add to resources:
public class ColorConverter : IValueConverter { #region IValueConverter Members public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { switch ((Color)value) { case Color.Red: return Colors.Red; case Color.Blue: return Colors.Blue; case Color.Green: return Colors.Green; default: throw new ArgumentOutOfRangeException("value"); } } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); } #endregion }
Significantly cleaner;) I hope this helps. If you have any questions, I will answer them in the comments!