views:

54

answers:

3

Hi All--

I'd like to apply a Brush (LinearGradientBrush in this case) to two or more objects (TextBlocks) at once. The effect that I'd like is something like this:

alt text

Edit I cannot simply apply the same brush to both objects, as this will make both of them start red and go to blue (instead of the second one starting at a shade of purple).

alt text

I'm sure I'm overlooking something quick-n-easy...

Thanks, wTs

A: 

Declare the brush into the window (or application) resources and bind the Foreground property of the two textblocks with the brush.

Jérémie Bertrand
Thanks, but that won't work (see updated question). See the difference? Note: I assume you mean Foreground, not Background.
Wonko the Sane
I think this will do what his second example shows, which is the behavior he does not want.
marr75
Ok, I haven't seen the update. And yes, I made a mistake with the Background, thanks for the signalisation.
Jérémie Bertrand
+1  A: 

What about using an ObjectDataProvider that exposes a method that returns the brush you want based on 3 integers, the starting x position of the brush, the current x position of the brush, and the ending x position of the brush (I could see use cases where you might want four parameters, x start, x end, x current start, x current end, but the 3 parameter will work for the case you have asked for). You can either statically assign these integers based on the layout of your control or use databinding for the parameters.

If you are unfamiliar with ObjectDataProvider and binding to method parameters for this class, i suggest going here and here

marr75
It would probably work, but seems much too complex for something that should be, I was hoping, fairly straight forward, like layering in any graphics program.
Wonko the Sane
+4  A: 

I did it like this:

<Border Height="100" Width="600" >
    <Border.OpacityMask>
        <VisualBrush>
            <VisualBrush.Visual>
                <StackPanel>
                    <TextBlock FontSize="85.333" FontFamily="Calibri" TextAlignment="Right">
                        The big first line
                    </TextBlock>
                    <TextBlock TextWrapping="Wrap" Margin="0,0,8,0" FontSize="32" FontFamily="Calibri" Text="The small second line" TextAlignment="Right" />
                </StackPanel>
            </VisualBrush.Visual>
        </VisualBrush>
    </Border.OpacityMask>
    <Border.Background>
        <LinearGradientBrush EndPoint="0.974,0.49" StartPoint="0,0.457">
            <GradientStop Color="#FFFD0202"/>
            <GradientStop Color="#FF0234FD" Offset="1"/>
        </LinearGradientBrush>
    </Border.Background>
</Border>

So, a border whose background is filled with the gradient from blue to red. The only visible part of the gradient is the text in the opacity mask.

Maybe some simpler control than the border would be even better. alt text

The remaining issue is that one has to size the container control explicitly, as it has no content.

Timores
Works, but it still seems there should be an easier way. For this to work properly, you will need to duplicate the content of the VisualBrush as Transparent TextBoxes for things to be sized automatically, or do a lot of code-behind arrange/measure magic to make it fit, or set it's alignment to Stretch and hope the aspect ratio is close enough, or... It just seems that there should be a neater way.
Wonko the Sane
You could factor out the behavior from either of the two workable answers into a user control. Your task is not an incredibly common one for other WPF developers so it makes since that if it is a common one for you, you make it into a user control.
marr75
Oh, I understand that it's not necessarily common; I'm just surprised that it's (seemingly) unnecessarily complex.
Wonko the Sane
I agree with @marr75, a UserControl would make this easier, as it could put its content in the VisualBrush and in a transparent content.
Timores
@Wonko the Sane: do you know of another technology that makes this easier ? Just out of curiosity.
Timores
As for duplicating the content of the visual brush, make this a dependency property of the user control and bind to it in both places it will be used in the user control, then make it's visibility hidden (not collapsed).
marr75
@Timores - it depends on what you mean by "technology". This is something that is fairly basic in any image editing software (Photoshop, Paint.NET, etc.), using selection and/or layers.
Wonko the Sane