ComboBox 绑定仅适用于 Color 属性 的一种方式

ComboBox binding works only one way with Color property

我正在实施 ObservableCollection <-> DataGrid 绑定。 我的 class 由一个 System.Windows.Media.Color 字段(名为 'Color')和几个字符串组成。

我在 Color 列的 WPF 中的实现:

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

和颜色属性:

<ObjectDataProvider x:Key="ColorProperties" ObjectType="{x:Type color:ColorHelper}" 
                    MethodName="GetColorNames"/>

ColorHelper class(我会尝试找到 OP 以示感谢):

public static class ColorHelper
{
    public static IEnumerable<string> GetColorNames()
    {
        foreach (PropertyInfo p
          in typeof(Colors).GetProperties(
          BindingFlags.Public | BindingFlags.Static))
        {
            yield return p.Name;
        }
    }
}

效果很好,我可以看到包含所有颜色的组合框:

现在我向 ObservableCollection 添加了几个对象,它们各自的字段填充到 DataGrid 中。除颜色外的所有内容。

默认颜色为黑色,但是当我 运行 应用程序时,组合框保持为空。

当我 select 来自 ComboBox 的颜色时,ObservableCollection 会相应地改变。但是,如果我更改对象本身,组合框将保持其原始值。

为了排除故障,我添加了

<DataGridTextColumn Header="Color" Binding="{Binding Color, UpdateSourceTrigger=LostFocus}" 
                    Width="100"/> 

此列填充了颜色的字符串表示形式,当我更改任一侧的值时,它会相应地发生变化。 这个事实表明 ComboBox 实现中缺少某些东西。

我是不是漏掉了某种翻译方法?看起来很奇怪,因为它实际上以一种方式工作(从组合框到对象)。

我到处寻找解决方案,但没有成功。

编辑: 我实现了 Color<->String 转换器,仍然无法正常工作..

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 更改:

<ComboBox ItemsSource="{Binding Source={StaticResource ColorProperties}}" 
                                              SelectedItem="{Binding Path=Color, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, 
                                                             Converter={StaticResource StringToColorConverter}}"
                                              Style="{StaticResource ComboBoxFlatStyle}">

有什么想法吗?

谢谢!

Combobox绑定的列表是一个字符串列表,而实际的对象不仅仅是一个字符串。您需要一个转换器,将字符串转换为您想要的对象。

其余一切似乎都很好,系统用户知道字符串 Black 如何转换为 Color Black

-- 绑定的一种方式是因为颜色对象知道如何从字符串中获取颜色,这就是为什么当我们设置 Background="String" 时它使用 FromName

获取相应的对象

好的,我发现出了什么问题。看起来从颜色中获取实际名称并不是那么简单。 ToString returns 十六进制字符串,而不是实际的颜色名称。 所以我使用 http://www.blogs.intuidev.com/post/2010/02/05/ColorHelper.aspx 的答案来创建转换器。

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);
    }
}