views:

1127

answers:

3

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

+2  A: 

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.

Andy
A: 

This is a little late, but take a look at using a StaticResource or a DynamicResource instead of a Binding - it will allow you to access another Resource. Not quite Binding, but it's better than nothing.

Andrew Dunkman
This sounds like it might work if I used a DynamicResource call... then specified it inside the StackPanels.Resources property maybe? I'll test and see what I can find. Never too late to answer a question on SO!
Nidonocu
A: 

Hi, I don't have answer to that question but I would like to ask it in another way hopefully both of us will get answers.

I have this DataTemplate:

<DataTemplate DataType="{x:Type local:GraphAdapter}">
    <DataTemplate.Resources>
        <VisualBrush 
          x:Key="NotMutualBrush"
          TileMode="Tile" Viewport="0,0,10,10" 
          ViewportUnits="Absolute" Viewbox="0,0,10,10"    
          ViewboxUnits="Absolute">
            <VisualBrush.Visual>
                <Canvas>
                    <Rectangle Width="10" Height="10">
                        <Rectangle.Fill>
                            <SolidColorBrush Color="{Binding VisualLink.LinkColor}" />
                        </Rectangle.Fill>
                    </Rectangle>
                    <Path Stroke="LightGray" Data="M 0 0 l 10 10" />
                    <Path Stroke="LightGray" Data="M 0 10 l 10 -10" />
                </Canvas>
            </VisualBrush.Visual>
        </VisualBrush>
    </DataTemplate.Resources>

    <Button 
        x:Name="TheButton"
        BorderBrush="LightBlue"
        Command="{Binding CenterOnMeCommand}"
        CommandParameter="{Binding}"
        >
        <Button.Background>
            <SolidColorBrush Color="{Binding VisualLink.LinkColor}" />
        </Button.Background>
        <TextBlock Text="{Binding VisualLink.ToolTipTitle}" TextWrapping="Wrap" />
    </Button>

    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding VisualLink.Link.IsMutual}" Value="False">
            <Setter TargetName="TheButton" Property="Background" Value="{StaticResource NotMutualBrush}" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

The point is I would like to paint the background in LinkColor for mutual links and the cross-visual-brush for non-mutual links.

In this way I have to have a resource with Binding but we, as you say in previous answers, the resource get created only once and the Binding does not work. I also try to put the VisualBrush right into Setter.Value but it had the same result and same warning in the Visual Studio Output window.

Any suggestions will be helpful.

Thank you, Ido

Ido Ran