Brush MVVM Binding does not give named color

2019-09-05 22:51发布

问题:

I have a MVVM binding for Border background where in I read Color names from a file in String format and convert them to Brush using the code:

Brush b1 = new SolidColorBrush((Color)ColorConverter.ConvertFromString("Red");
myItem.Background = b1;

Background is a property defined in ViewModel as:

public Brush Background
{
    get { return _background; }
    set
    {
        this._background = value;
        RaisePropertyChanged("Background");
    }
}

And it is accessed in XAML as:

<Border Background="{Binding Background}">
    <Border.Style>
        <Style TargetType="{x:Type Border}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Background}" Value="Red">
                    <Setter Property="Height" Value="40"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Border.Style>
</Border>

The border is properly colored- no issues there.

The problem is DataTrigger is never triggered because when I see the value of this._background in set method, it is "#FFFF0000" and it is not equal to Brushes.Red (i tried converting value to SolidColorBrush and then compared with Brushes.Red, but it is not equal).

What is that I am doing wrong? What can I do to ensure that the color names that I read from a file are properly converted into Brushes.* so that my DataTrigger works fine.

Thanks,

RDV

回答1:

Yes, Brushes.Red is a SolidColorBrush. Not a color, a brush. Confusion arises from the implicit conversion of the string "Red", in the XAML, into a Brush object. But a new SolidColorBrush instance with a Color that is also equal to #FFFF0000 will be a different instance of SolidColorBrush, and they won't be "equal" to one another.

But you don't care which brush instance it is; you care about the color. So compare the color. (Brushes.Red.Color == Colors.Red) == true. Color is a value type, not a reference type, so two equivalent values will be considered equal.

<DataTrigger 
    Binding="{Binding Background.Color, RelativeSource={RelativeSource Self}}" 
    Value="Red">

Notice that Background isn't a property of the DataContext. That was a second thing that wasn't working with your code. You need to explicitly tell the Binding to look not at the DataContext, but at the control itself, to find the property referred to in the Path. RelativeSource={RelativeSource Self} does that. "Background.Color" is the Path parameter for the Binding. Path is the default, so you don't have to explicitly name it. But you could:

<DataTrigger 
    Binding="{Binding Path=Background.Color, RelativeSource={RelativeSource Self}}" 
    Value="Red">