Это довольно просто на самом деле.
Путь - это объект WPF, и поэтому каждый объект WPF может иметь только 1 родительский объект. Если у объекта WPF установлен родительский объект, его нельзя использовать в другом родительском объекте.
Что происходит, DataTemplate загружается и показывает ваши элементы. Вы выбираете один элемент с помощью Path, и он устанавливается в ContentPresenter Selected Item вашего Combobox (он должен быть показан). Это отсоединяет Путь от вашего исходного объекта, в результате чего ваши предметы «исчезают». Ваши предметы все еще присутствуют, но вы не можете их видеть, потому что у них больше нет видимого объекта, поскольку Путь был отсоединен от вашего исходного списка. В случае строки это работает, потому что строка не является объектом WPF.
Надеюсь, это немного прояснит ситуацию.
Итак, теперь для решения:
Если вы хотите сохранить зеленый как текст, вы можете сделать следующее:
Создайте свой ColorList типа Color enum:
public class ColorList : List<Color> { }
Выбросьте некоторые вещи:
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
}
И разверните свой DataTemplate, чтобы установить конкретную матрицу данных для красного и синего, используя объекты Trigger в вашем 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>
Чистый подход:
Если вы хотите, чтобы все элементы были цветными объектами, вам потребуется объект-конвертер для преобразования значения перечисления Color в цвет, который вы хотите показать:
<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>
И хороший конвертер, который нужно добавить в ресурсы:
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
}
Намного чище;) Надеюсь, это поможет .. если у вас есть какие-либо вопросы, я отвечу на них в комментариях!