R – Enable data binding in shared WPF resources inside a ResourceDictionary

data-bindingresourcedictionarywpf

I'm using the M-V-VM pattern in WPF and I have a background brush I'm going to be using rather often and I'd like to move it out in to a shared ResourceDictionary.

The only problem is the brush uses a color which it gets via Databinding to its hosted context.

Is there anyway I can move the brush out in to a ResourceDictionary and still have it find the value it needs?

The Brush:

<RadialGradientBrush>
    <RadialGradientBrush.RelativeTransform>
        <TransformGroup>
            <ScaleTransform CenterX="0.5"
                            CenterY="0.5"
                            ScaleX="2.3"
                            ScaleY="2.3" />
            <TranslateTransform X="-0.3"
                                Y="-0.3" />
        </TransformGroup>
    </RadialGradientBrush.RelativeTransform>
    <GradientStop Color="{Binding Path=BackdropColor}"
                  Offset="1.2" />
    <GradientStop Color="#FFFFFFFF"
                  Offset="-0.1" />
</RadialGradientBrush>

After re-factoring it out to a ResourceDictionary and adding a key, I called it as such:

<StackPanel Grid.Row="0"
            Margin="0,0,0,0"
            Orientation="Horizontal"
            Background="{DynamicResource BackdropRadGradBrush}">

But this resulted in this output in the debugger:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=BackdropColor; DataItem=null; target element is 'GradientStop' (HashCode=16001149); target property is 'Color' (type 'Color')

Best Answer

I don't think that you can keep this Brush in your resource dictionary and use binding to pull in the color. Since the brush is only created once (which is why you want it in the resource dictionary in the first place), at the time of creation WPF doesn't know where it will be used, so it can't pull in the value for the color.

If the color were kept in Setings, for example, that would probably work - but I'm guessing that won't help you, because you probably want the color to change on each control that it is used on (otherwise, you could just hard code the color or it would already be in settings).

Maybe you could create a RadialGradientBrush subclass, and expose the first GradientStop color as a DependencyProperty? You could then create an instance of this subclass wherever you need it, and use binding to pull in the correct color there.

Related Topic