How to merge an image into the background along two edges? - c#

I'm trying to create a stylish effect in my app that allows an image to sit in the top right hand corner with the left and bottom edges merging into the background colour using Image.OpacityMask. Something like:
This could be done using the following code, except Image.OpacityMask only allows for one child LinearGradientBrush:
<Image Source="Images/poster.jpg" Width="300">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="1, 0.5" EndPoint="0, 0.5">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
How can I create an Image.OpacityMask like this with valid code? I'm aware that there is a RadialGradientBrush, but this would blend the whole image, not just the left and bottom edges.

You could use two elements, e.g. an Image in a Border:
<Border HorizontalAlignment="Right" VerticalAlignment="Top" Width="300">
<Border.OpacityMask>
<LinearGradientBrush StartPoint="1, 0.5" EndPoint="0, 0.5">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Border.OpacityMask>
<Image Source="Images/poster.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0.5, 0" EndPoint="0.5, 1">
<GradientStop Color="Black" Offset="0.2" />
<GradientStop Color="Transparent" Offset="1.0" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
</Border>

Related

WPF, TextBlock with RotateTransform & LinearGradientBrush

I have textblock like this
<TextBlock Text="BETA"
FontSize="28"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Margin="0,17,420,271"
FontFamily="Georgia">
<TextBlock.RenderTransform>
<RotateTransform Angle="20" />
</TextBlock.RenderTransform>
<TextBlock.Foreground>
<LinearGradientBrush StartPoint="0,0"
EndPoint="0,24"
MappingMode="Absolute">
<GradientStopCollection>
<GradientStop Color="White"
Offset="0" />
<GradientStop Color="Orange"
Offset=".2" />
<GradientStop Color="DarkOrange"
Offset=".85" />
<GradientStop Color="White"
Offset="1" />
</GradientStopCollection>
</LinearGradientBrush>
</TextBlock.Foreground>
</TextBlock>
It won't render any text. If I remove the transform OR the brush then it works fine but both together won't render anything.
Removing Absolute as the mapping mode fixed my issue? Not sure why.

How to Insert an Image above Background

I can create the rectangle with the gradient background. How to insert a picture above it by giving its path?
<Rectangle StrokeThickness="2" Height="77" Canvas.Left="184" Canvas.Top="477" Width="119">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="White" Offset="0.5" />
<GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
What I want:
The Border will hold one piece of content, so if that is all you have, the following will work just fine:
<Border>
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Border.Background>
<Image HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
If you need to layer more shapes/paths/images then you can use a Grid object which supports multiple children :
<Grid>
<!--Object 1-->
<Ellipse StrokeThickness="2"
Height="77"
Width="119"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Ellipse.Fill>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
<!--Object 2-->
<Image HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
Just remember that WPF starts drawing controls from the beginning of your XAML, so the last control defined in the XAML listing is the one that gets drawn on top.
Since Rectangle does not support direct content, you can place your image where you want in relation to your rectangle and give it a higher Canvas.ZIndex property so it will render on top of your rectangle.
Ex:
<Rectangle StrokeThickness="2"
Height="77"
Canvas.Left="184"
Canvas.Top="477"
Width="119"
Canvas.ZIndex="1">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0,0.5"
EndPoint="1,0.5">
<GradientStop Color="Black"
Offset="0" />
<GradientStop Color="White"
Offset="0.5" />
<GradientStop Color="Black"
Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Image Height="50"
Canvas.Left="184"
Canvas.Top="477"
Width="50"
Canvas.ZIndex="2" />
EDIT
Centering the image in the rectangle always is a different problem. You could have a property in your code behind that represents the calculated center coordinates of your rectangle that changes when you move your rectangle (through events). You could then bind your image location to that property.

WPF: Image as Background with Opacity Mask

I haven't been able to get this to work, but this is what I envision:
Essentially, I want to have a control in WPF where the background is set to a left aligned image with an opacity mask that fades the right side of the image out into transparency (so that the parent's background color shows through)
Is this type of thing possible? Here's what I've tried:
<DockPanel x:Name="ContentPanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<DockPanel.Background>
<ImageBrush ImageSource="test.jpg" Stretch="None" AlignmentX="Left" AlignmentY="Center" />
</DockPanel.Background>
<DockPanel.OpacityMask>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="0.5"/>
</LinearGradientBrush>
</DockPanel.OpacityMask>
</DockPanel>
This example should get you started.
<Grid>
<Grid.Resources>
<Image x:Key="myImage" Source="test.jpg">
<Image.OpacityMask>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5" >
<GradientStop Offset="0.0" Color="#00000000" />
<GradientStop Offset="1.0" Color="#FF000000" />
</LinearGradientBrush>
</Image.OpacityMask>
</Image>
<VisualBrush x:Key="myBrush" Visual="{StaticResource myImage}"/>
</Grid.Resources>
<DockPanel x:Name="ContentPanel" Width="550"
HorizontalAlignment="Left"
Background="{StaticResource myBrush}"/>
</Grid>
You could also use a partially transparent bitmap (png). That way you can have more complex transparency effects than just a gradient.
Like this: (replace the underlying rectangle with any image u want)
<Grid x:Name="LayoutRoot">
<Rectangle Margin="187,91,147,101" Stroke="Black">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle Margin="254,164,196,158" Stroke="Black" Fill="Red">
<Rectangle.OpacityMask>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#00000000"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</Grid>

How to make a dotted border on a Border element in Silverlight?

How can I make the bottom border of this Border Silverlight element have a red dotted inside of a red solid line?
Border border = new Border();
border.CornerRadius = new CornerRadius(5);
border.BorderThickness = new Thickness(0, 0, 0, 1);
border.BorderBrush = new SolidColorBrush(Colors.Red);
Can you replace the border with a Grid and give it a Rectangle that fills the whole area?
<Rectangle Stretch="Fill" RadiusX="10" RadiusY="10" StrokeDashArray="10, 2" Stroke="Black" Fill="White" />
The StrokeDashArray can be used to draw it dotted but a Border has no such property.
EDIT:
Since I noticed you are only dotting the bottom border you could do something like this
<Border Width="100" Height="100" Background="Blue" BorderThickness="0,0,0,1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint=".2,0" SpreadMethod="Repeat" >
<GradientStopCollection>
<GradientStop Color="Transparent" Offset="0" />
<GradientStop Color="Transparent" Offset="0.3" />
<GradientStop Color="Red" Offset="0.3" />
<GradientStop Color="Red" Offset="0.6" />
<GradientStop Color="Transparent" Offset="0.6" />
<GradientStop Color="Transparent" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
Adjust the Offset of the middle two GradientStop's to adjust the width of the red dot/dash. You may also need to adjust the endpoint to make it repeat at your desired interval.
Stephan's answer is helpful. However if you want a simple dotted line that doesn't stretch about as it is resized, try this XAML:
<!-- Horizontal dotted line -->
<Border HorizontalAlignment="Stretch" Height="1" BorderThickness="0,0,0,1">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="2,0"
SpreadMethod="Repeat" MappingMode="Absolute">
<GradientStop Color="Transparent" Offset="0" />
<GradientStop Color="Transparent" Offset="0.499" />
<GradientStop Color="#999" Offset="0.5" />
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
Here's an alternative for a vertical dotted line:
<!-- Vertical dotted line -->
<Border VerticalAlignment="Stretch" Width="1" BorderThickness="0,0,1,0">
<Border.BorderBrush>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,2"
SpreadMethod="Repeat" MappingMode="Absolute">
<GradientStop Color="Transparent" Offset="0" />
<GradientStop Color="Transparent" Offset="0.499" />
<GradientStop Color="#999" Offset="0.5" />
</LinearGradientBrush>
</Border.BorderBrush>
</Border>
Coincidentally, if you use this brush on an area that's not 1px wide/tall, then you get a nice pinstripe pattern.

WPF Rounded corners - is a consistent gradient around the corner possible?

I've made a gradient that I quite like in expression blend, and I'm trying to work out if I can make the gradient curve around a corner, to give me a rounded border effect with the gradient.
The problem is that I can't use a normal border, because the gradient wont be consistent.
I came up with the following which should help demonstrate what I'm thinking:
rounded corner with gradient http://img232.imageshack.us/img232/9899/roundedcornerrg0.th.jpg
<Grid x:Name="grid" >
<Border
BorderThickness="0,0,40,40"
CornerRadius="0,0,40,0"
Padding="2" Height="60" VerticalAlignment="Bottom" Width="65" HorizontalAlignment="Right" >
<Border.BorderBrush>
<RadialGradientBrush>
<RadialGradientBrush.RelativeTransform>
<TransformGroup>
<ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="2.058" ScaleY="2.177"/>
<SkewTransform AngleX="0" AngleY="0" CenterX="0.5" CenterY="0.5"/>
<RotateTransform Angle="-119.481" CenterX="0.5" CenterY="0.5"/>
<TranslateTransform X="0.209" Y="0.52"/>
</TransformGroup>
</RadialGradientBrush.RelativeTransform>
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</RadialGradientBrush>
</Border.BorderBrush>
</Border>
<Rectangle VerticalAlignment="Stretch" Height="100" Width="40" HorizontalAlignment="Right" Margin="0,0,0,60" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="-0.025,0.5" StartPoint="1,0.5">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="40" Width="100" HorizontalAlignment="Stretch" Margin="0,0,65,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0"/>
<GradientStop Color="#000A0A0A" Offset="1"/>
<GradientStop Color="#6B050505" Offset="0.829"/>
<GradientStop Color="#BB020202" Offset="0.763"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
Is there any way to get a gradient bending around a corner like I'm thinking? I saw a suggestion online to nest borders in each other, but this is no good for me either, as the gradient makes life difficult.
You might want to check out Charles Petzolds article on Graphical Paths with Gradient Colors in which he discusses a similar problem to yours.
<Grid x:Name="grid" VerticalAlignment="Top" HorizontalAlignment="Left" Width="100" Height="100" Margin="200,200,0,0">
<Rectangle VerticalAlignment="Stretch" Width="20" HorizontalAlignment="Right" Margin="0,20,0,20" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0" StartPoint="0,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" HorizontalAlignment="Stretch" Margin="20,0,20,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,1" StartPoint="1,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Stretch" Width="20" HorizontalAlignment="Left" Margin="0,20,0,20" StrokeThickness="0" Panel.ZIndex="0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" HorizontalAlignment="Stretch" Margin="20,0,20,0">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1,0" StartPoint="1,1">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" Width="20" HorizontalAlignment="Left" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".9,.9" GradientOrigin="1,1" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" Width="20" HorizontalAlignment="Right" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".1,.1" GradientOrigin="0,0" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Top" Height="20" Width="20" HorizontalAlignment="Right" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".1,.9" GradientOrigin="0,1" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
<Rectangle VerticalAlignment="Bottom" Height="20" Width="20" HorizontalAlignment="Left" Margin="0,0,0,0">
<Rectangle.Fill>
<RadialGradientBrush Center=".9,.1" GradientOrigin="1,0" RadiusX=".85" RadiusY=".85">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
<GradientStop Color="#22FFFFFF" Offset="0.5"/>
<GradientStop Color="#11FFFFFF" Offset="0.3"/>
</RadialGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>

Categories