I created a ComboBox listing the colors that System.Windows.Media.Colors predefines, using the approach told in this question: How can I list colors in WPF with XAML?
My XAML code now is:
<Window ...>
<Window.Resources>
<ObjectDataProvider
ObjectInstance="{x:Type Colors}" MethodName="GetProperties" x:Key="ColorList" />
<local:StringToBrushConverter x:Key="FontColorConversions" />
</Window.Resources>
<Grid Background="Black">
...
<ComboBox Grid.Column="1" Grid.Row="1" Height="22" Width="240"
VerticalAlignment="Center" HorizontalAlignment="Left"
ItemsSource="{Binding Source={StaticResource ColorList}}"
SelectedValue="{Binding FontColor, Mode=TwoWay}"
DisplayMemberPath="Name"
SelectedValuePath="Name">
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="{Binding Converter={StaticResource FontColorConversions}}"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
...
</Grid>
</Window>
And besides, please note that I bind SelectedValue to a VM class's FontColor property, which is of string type.
class FontSetting : INotifyPropertyChanged
{
private string _fontColor = "Lavender"; // initial color
public event PropertyChangedEventHandler PropertyChanged;
public string FontColor
{
get
{
return _fontColor;
}
set
{
_fontColor = value;
OnPropertyChanged("FontColor");
}
}
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
And I set the DataContext of the Window containing this ComboBox to an instance of FontSetting.
So each item in the ComboBox actually display a string representing a certain color now, what I want to do is set an item's Foreground color to that color its content indicates, like this:
Can anyone help? Thanks.
UPDATED: Since most of the solutions have a converter which converts string to Brush and actually I already have it, now I want to put mine here, as I binded a TextBox's Foreground to FontSetting's FontColor property, so that when you change the ComboBox, the color of that TextBox changes accordingly.
Here is my converter class, and it works fine by now:
class StringToBrushConverter : IValueConverter
{
public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
BrushConverter conv = new BrushConverter();
SolidColorBrush brush = conv.ConvertFromString("Lavender") as SolidColorBrush;
if (null != value)
{
brush = conv.ConvertFromString(value.ToString()) as SolidColorBrush;
}
return brush;
}
public object ConvertBack(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
When I click the ComboBox to open the dropdown list, I got an exception:
CONCLUSION
Amine's solution works, it's my mistake. I explain briefly now, if you bind a ComboBox to System.Windows.Media.Colors like what I am doing, when the item is rendered, the Convert() method of the converter class (which you assign to the binding) is executed, and actually the value passed to Convert() as its first parameter is a Syetem.Windows.Media.Color instance. I made mistake coz I thought it was of string type.
Therefore, in my case I need two converter classes, one converting string to Brush, and the other one converting Color to Brush. So I will keep my own StringToBrush converter and add Amine's ColorToBrush converter.
However, I simplified Amine's implementation a bit:
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BrushConverter conv = new BrushConverter();
SolidColorBrush brush = SolidColorBrush)conv.ConvertFromString(FontSetting.DEFAULT_FONT_COLOR);
if (null != value)
{
PropertyInfo pi = value as PropertyInfo;
if (null != pi)
{
brush = conv.ConvertFromString(pi.Name) as SolidColorBrush;
}
}
return brush;
}
Moreover, Joe's input is also valuable, put all them together, I can keep the items' color consistent, which is perfect.