How can I apply a GradientBrush to multiple consecutive objects in XAML?
Question
I have a TextBlock and a Line sitting next to each other in their own exclusive StackPanel.
I need to spread my LinearGradientBrush across the two objects, rather than shading them individually.
My project currently looks like this:
http://img188.imageshack.us/img188/1268/seperategradients.png
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Bottom">
SomeTextContent
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="Orange" />
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
<Line VerticalAlignment="Bottom" X2="100">
<Line.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="Blue" />
<GradientStop Offset="1" Color="Orange" />
</LinearGradientBrush>
</Line.Stroke>
</Line>
</StackPanel>
As shown, the gradient is applied to TextBlock seperately from the Line. I need to find a way to apply the gradient across the TextBlock and the Line in a single pass - as if they were the same object entirely. In this example, the text should be mostly blue and the line should be mostly orange.
Solution
In WPF you can use a Visual Brush.
Add a brush resource to your window or control resources:
<Window.Resources>
<VisualBrush x:Key="stackPanel">
<VisualBrush.Visual>
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Bottom">
SomeTextContent
</TextBlock>
<Line VerticalAlignment="Bottom" X2="100" Stroke="black"/>
</StackPanel>
</VisualBrush.Visual>
</VisualBrush>
</Window.Resources>
Next, apply that brush to the opacitymask of a rectange, for example:
<Rectangle OpacityMask="{DynamicResource stackPanel}">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1.0,0.5" StartPoint="0,0.5">
<GradientStop Color="Blue" Offset="0"/>
<GradientStop Color="Orange" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
You can turn the text into a path too, but you'll loose the ability to change the text than.
OTHER TIPS
Your problem is that text is not a vector and so cannot be combined with the line (any way that I know of).
I believe that it is possible to change text into a vector path in Expression Blend and then use that to create a clipping path over the gradient. Or, using the text vector path like you would do with your line, use a background colour unrestricted-height border and transparent fill on the vector itself.
Seems like a lot of trouble to go to. Have you thought about using a third colour to merge the two? For example text block fade from Blue to Orange, then on the line Orange to the background colour. You might be able to get a similar effect for a lot less effort.