Reputation: 3013
I'm implementing an ObservableCollection
<-> DataGrid
binding.
My class consists of a System.Windows.Media.Color
field (named 'Color') and several strings.
My implementation in WPF of the Color column:
<DataGridTemplateColumn Header="Color" Width="100">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource ColorProperties}}"
SelectedItem="{Binding Path=Color, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
Style="{StaticResource ComboBoxFlatStyle}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="1" Orientation="Horizontal">
<Rectangle Fill="{Binding}" Height="10" Width="10" Margin="2"/>
<TextBlock Text="{Binding}" Margin="2,0,0,0"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
And ColorProperties:
<ObjectDataProvider x:Key="ColorProperties" ObjectType="{x:Type color:ColorHelper}"
MethodName="GetColorNames"/>
The ColorHelper class (I'll try to find the OP for credit):
public static class ColorHelper
{
public static IEnumerable<string> GetColorNames()
{
foreach (PropertyInfo p
in typeof(Colors).GetProperties(
BindingFlags.Public | BindingFlags.Static))
{
yield return p.Name;
}
}
}
This works just fine, I can see the combo-box with all the colors:
Now I added a few objects to the ObservableCollection, and their respective fields are populated in the DataGrid. All except the Color.
The default Color is Black, but when I run the application, the ComboBox stays empty.
When I select a color from the ComboBox, the ObservableCollection changes accordingly. However if I change the object itself, the ComboBox stays with its original value.
For troubleshooting, I added
<DataGridTextColumn Header="Color" Binding="{Binding Color, UpdateSourceTrigger=LostFocus}"
Width="100"/>
This column gets populated with the string representation of the color, and when I change the value from either side, it changes accordingly. This fact suggests that there's something missing in the ComboBox implementation.
Am I missing some sort of translation method? Seems weird since it actually works in one way (from ComboBox to object).
I've searched everywhere for a solution, without success.
EDIT: I implemented Color<->String converter, still doesn't work..
public class StringToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Color content = (Color)value;
return content.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string content = (string)value;
return (Color)ColorConverter.ConvertFromString(content);
}
}
WPF change:
<ComboBox ItemsSource="{Binding Source={StaticResource ColorProperties}}"
SelectedItem="{Binding Path=Color, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay,
Converter={StaticResource StringToColorConverter}}"
Style="{StaticResource ComboBoxFlatStyle}">
Any ideas?
Thanks!
Upvotes: 2
Views: 540
Reputation: 3013
OK i found out what was wrong. It looks like getting the actual name from a color is not that simple. ToString returns the hex string, and not the actual color name. So I used the answer from http://www.blogs.intuidev.com/post/2010/02/05/ColorHelper.aspx to create the converter.
public class ColorToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Color KnownColor;
Color content = (Color)value;
Type ColorType = typeof(System.Windows.Media.Colors);
PropertyInfo[] ColorsCollection = ColorType.GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (PropertyInfo pi in ColorsCollection)
{
KnownColor = (Color)pi.GetValue(null);
if (KnownColor == content)
return pi.Name;
}
return String.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string content = (string)value;
return (Color)ColorConverter.ConvertFromString(content);
}
}
Upvotes: 0
Reputation: 4116
The list bound to Combobox is a list of strings, whereas the actual object is not just a string. you need a converter that converts from string to your desired object.
Rest all seems fine, system dosent know how does string Black translates to Color Black
-- one way binding works because, color object knows how to get color from a string, that is why when we set Background="String" it get the corresponding object using FromName
Upvotes: 1