Solid transparent line in WPF gradient - wpf

I am trying to draw a transparent line in a solid block using a gradient:
<Grid>
<Border Margin="-102,-27,102,27">
<Border.Background>
<LinearGradientBrush EndPoint="517,160" StartPoint="0,160" MappingMode="Absolute">
<GradientStop Color="#FF2DBCF2" Offset="0"/>
<GradientStop Color="#FF2DBCF2" Offset="1"/>
<GradientStop Color="#002DBCF2" Offset="0.0091" />
<GradientStop Color="#FF2DBCF2" Offset="0.009"/>
<GradientStop Color="#002DBCF2" Offset="0.015"/>
<GradientStop Color="#FF2DBCF2" Offset="0.0151"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</Grid>
The problem is that on the edges of the gap in the solid colour block there is a faint fading effect which makes the edge slightly less than crisp. Is there a way to get rid of this faint fading? I just can't seem to find a way around it.

You may use something like the following DrawingBrush for the background:
<Border Margin="-102,-27,102,27">
<Border.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="#FF2DBCF2">
<GeometryDrawing.Geometry>
<GeometryGroup>
<RectangleGeometry Rect="0,0,0.01,1"/>
<RectangleGeometry Rect="0.015,0,0.985,1"/>
</GeometryGroup>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Border.Background>
</Border>

The only way to get a sharp line in the background is to use an ImageBrush or DrawingBrush as background instead of a LinearGradientBrush
I can't work out a complete example right now, but this should get you started on how to implement a DrawingBrush as background.
<Border.Background>
<DrawingBrush TileMode="Tile" Stretch="None" Viewport="0,0,20,20" ViewportUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing>
<GeometryDrawing.Pen>
<Pen Brush="White"/>
</GeometryDrawing.Pen>
<GeometryDrawing.Geometry>
<LineGeometry StartPoint="0.3,0"
EndPoint="0.3,20"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
<Border.Background>

Related

How to get DrawingImage out of the Style?

I had the DrawingBrush placed as below -
<DrawingBrush Viewbox="0,0,39.125,39.125" ViewboxUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=uiEntityViews:NodeCanvasView}, Path=MyColor}" Geometry="F1M19.5625,0.999954C29.8144,0.999954 38.125,9.31053 38.125,19.5625 38.125,29.8142 29.8143,38.1249 19.5625,38.1249 9.31073,38.1249 1,29.8142 1,19.5625 1,9.31053 9.31064,0.999954 19.5625,0.999954z">
<GeometryDrawing.Pen>
<Pen DashCap="Square" EndLineCap="Flat" LineJoin="Round" MiterLimit="10" StartLineCap="Flat" Thickness="2">
<Pen.Brush>
<LinearGradientBrush EndPoint="0.849422,0.849423" StartPoint="0.150577,0.150578">
<GradientStop Color="#FF657783" Offset="0"/>
<GradientStop Color="White" Offset="0.146"/>
<GradientStop Color="#FF2C4758" Offset="1"/>
</LinearGradientBrush>
</Pen.Brush>
<Pen.DashStyle>
<DashStyle/>
</Pen.DashStyle>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
With this, I can get image from DrawingBursh as follows -
if (resourceObject is DrawingBrush)
{
DrawingBrush iconBrush = resourceObject as DrawingBrush;
DrawingImage image = new DrawingImage(iconBrush.Drawing);
resourceObject = image;
}
Now, I added the DrawingBrush within the style like below -
<Style x:Key="MY_ICON_STYLE" TargetType="Rectangle">
<Setter Property="Fill">
<Setter.Value>
<DrawingBrush Viewbox="0,0,39.125,39.125" ViewboxUnits="Absolute">
<DrawingBrush.Drawing>
<GeometryDrawing Brush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=uiEntityViews:NodeCanvasView}, Path=MyColor}" Geometry="F1M19.5625,0.999954C29.8144,0.999954 38.125,9.31053 38.125,19.5625 38.125,29.8142 29.8143,38.1249 19.5625,38.1249 9.31073,38.1249 1,29.8142 1,19.5625 1,9.31053 9.31064,0.999954 19.5625,0.999954z">
<GeometryDrawing.Pen>
<Pen DashCap="Square" EndLineCap="Flat" LineJoin="Round" MiterLimit="10" StartLineCap="Flat" Thickness="2">
<Pen.Brush>
<LinearGradientBrush EndPoint="0.849422,0.849423" StartPoint="0.150577,0.150578">
<GradientStop Color="#FF657783" Offset="0"/>
<GradientStop Color="White" Offset="0.146"/>
<GradientStop Color="#FF2C4758" Offset="1"/>
</LinearGradientBrush>
</Pen.Brush>
<Pen.DashStyle>
<DashStyle/>
</Pen.DashStyle>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingBrush.Drawing>
</DrawingBrush>
</Setter.Value>
</Setter>
</Style>
In this case, I am not sure how to get DrawingImage out of this Style like below -
if (resourceObject is Style)
{
Style iconStyle = resourceObject as Style;
//How to get drawingImage out of iconStyle
// DrawingImage image = new DrawingImage(iconStyle.DrawingBrush);
//resourceObject = iconStyle;
}
if (resourceObject is Style)
{
Style iconStyle = resourceObject as Style;
if (iconStyle != null)
{
foreach (var setter in iconStyle.Setters.OfType<Setter>())
{
if (setter.Value is DrawingBrush)
{
DrawingBrush iconBrush = (DrawingBrush)setter.Value;
DrawingImage image = new DrawingImage(iconBrush.Drawing);
resourceObject = image;
break;
}
}
}
}

Create custom shape consisting of multiple single lines

i want to create a simple cross, that consists of two lines. The lines should have different colors. I've created a class that inherits form Shape. This class contains the two lines and computes the coordinates of the lines. I've read that i have to implement the DefiningGeometry property if i inherit from Shape. But how can i return both lines in the get section of that property?
Thanks in advance.
It sounds like you could use the CombinedGeometry Class to combine your lines together... the only thing is that you'll need to use LineGeometry classes instead of Lines. You could do something like this (from the linked CombinedGeometry page on MSDN):
<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF">
<Path.Data>
<!-- Combines two geometries using the XOR combine mode. -->
<CombinedGeometry GeometryCombineMode="Xor">
<CombinedGeometry.Geometry1>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="75,75" />
</CombinedGeometry.Geometry1>
<CombinedGeometry.Geometry2>
<EllipseGeometry RadiusX="50" RadiusY="50" Center="125,75" />
</CombinedGeometry.Geometry2>
</CombinedGeometry>
</Path.Data>
</Path>
Of course, you'd want to replace these EllipseGeometry objects with LineGeometry objects, but that shouldn't be difficult as they have similar properties.
UPDATE >>>
Unfortunately, I don't think that you can use a CombinedGeometry object that contains geometries of different colours... the whole shape would have to be painted with one Brush. However, you could fake two colours with cleverly positioned GradientStops. Also, as #Clemens mentioned, perhaps a GeometryGroup would be easier for you to use... try something like this:
<Path StrokeThickness="5" Fill="Blue" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path.Data>
<GeometryGroup>
<LineGeometry StartPoint="50,0" EndPoint="50,100" />
<LineGeometry StartPoint="0,50" EndPoint="100,50" />
</GeometryGroup>
</Path.Data>
<Path.Stroke>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Color="LightGreen" Offset="0" />
<GradientStop Color="LightGreen" Offset="0.475" />
<GradientStop Color="Red" Offset="0.475" />
<GradientStop Color="Red" Offset="0.525" />
<GradientStop Color="LightGreen" Offset="0.525" />
<GradientStop Color="LightGreen" Offset="0" />
</LinearGradientBrush>
</Path.Stroke>
</Path>
This Brush will appear as if it were actually different colours on the two lines:
Then all you'll need to do is to convert this into C# to return it from the DefiningGeometry property. Please use the examples from the linked pages and the GeometryGroup class page on MSDN to help you with this.
You may draw two differently colored lines by means of two GeometryDrawings in a DrawingBrush that fills a Rectangle:
<Rectangle Width="20" Height="20">
<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Geometry="M0,-10 L0,10">
<GeometryDrawing.Pen>
<Pen Brush="Blue" Thickness="3"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
<GeometryDrawing Geometry="M-10,0 L10,0">
<GeometryDrawing.Pen>
<Pen Brush="Red" Thickness="3"/>
</GeometryDrawing.Pen>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>

How to create a shape with a gradient fill, and add it to a border background in WPF

I am trying to create the following shape as a background to a border. You will notice that the bottom section on the shape has a linear gradient to it.
I have played around with lines and shapes and gradients, but i have not been able to apply the below to a border. nor can i get a shape that looks like that.
Is this even possible? if so, can anyone help
The below XAML produces a brush that looks similar to your picture. You should play around the colors, offsets, and the rest for the best appearance.
<DrawingBrush x:Key="br1" Viewbox="0,0,100,100" ViewboxUnits="Absolute" >
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="Lavender">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,100,100" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing>
<GeometryDrawing.Brush>
<RadialGradientBrush GradientOrigin="0.5,0.01" Center="0.5,-0.2" RadiusX="100">
<GradientStop Color="MidnightBlue" Offset="1.0" />
<GradientStop Color="LightSteelBlue" Offset="0.0" />
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Geometry>
<EllipseGeometry Center="60,310" RadiusX="160" RadiusY="300" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
Have fun!

Explicit geometry bounds

I encountered following problem during creation of radioactive geometry:
Orange dot represents RadialGradientBrush center point (0,0). It should be in the center of black circle, not on the bottom. This cause another problem: spinning animation.
Is there a way to fix this at the geometry level ? I could fix it by setting brush's center point explicitly, but that is inconvenient and brittle.
<GeometryDrawing>
<GeometryDrawing.Geometry>
<GeometryGroup>
<PathGeometry Figures="
M-10,0 Q0,5 10,0
Q20,25 25,50
Q0,60 -25,50
Q-20,25 -10,0 Z">
<PathGeometry.Transform>
<TranslateTransform Y="15" />
</PathGeometry.Transform>
</PathGeometry>
<PathGeometry Figures="
M-10,0 Q0,5 10,0
Q20,25 25,50
Q0,60 -25,50
Q-20,25 -10,0 Z" >
<PathGeometry.Transform>
<TransformGroup>
<TranslateTransform Y="15" />
<RotateTransform Angle="120" />
</TransformGroup>
</PathGeometry.Transform>
</PathGeometry>
<PathGeometry Figures="
M-10,0 Q0,5 10,0
Q20,25 25,50
Q0,60 -25,50
Q-20,25 -10,0 Z" >
<PathGeometry.Transform>
<TransformGroup>
<TranslateTransform Y="15" />
<RotateTransform Angle="240" />
</TransformGroup>
</PathGeometry.Transform>
</PathGeometry>
<EllipseGeometry RadiusX="10" RadiusY="10" />
</GeometryGroup>
</GeometryDrawing.Geometry>
<GeometryDrawing.Brush>
<RadialGradientBrush ColorInterpolationMode="ScRgbLinearInterpolation">
<GradientStop Offset="0" Color="Orange" />
<GradientStop Offset="0.03" Color="Black" />
</RadialGradientBrush>
</GeometryDrawing.Brush>
<GeometryDrawing.Pen>
<Pen Thickness="0">
<Pen.Brush>
<SolidColorBrush Color="Black" />
</Pen.Brush>
</Pen>
</GeometryDrawing.Pen>
</GeometryDrawing>
This is caused by the fact that the top of the box cuts off the top of the big circle. It is cut off because the top two petals are rotated.
You could fix this by adding the outer circle (transparent) to the geometry or perhaps by adding a margin to the top.
this will move down the black parts of the drawing, centering the orange dot and fixing the rotation.
Does this make sense? It is hard to explain, when needed I could create a sketch.

How to use application's resource from ControlTemplate?

I get this error
'disable_glow' name cannot be found in the name scope of 'System.Windows.Controls.ControlTemplate'.
when trying to do this:
Application's resources:
<LinearGradientBrush Opacity="0.0" StartPoint="0,0"
EndPoint="0,1" x:Key="disable_glow" x:Name="disable_glow">
<GradientStop Offset="0.0" Color="#4D4D4D" />
<GradientStop Offset="0.1" Color="#404040" />
<GradientStop Offset="1.0" Color="#2E2E2E" />
</LinearGradientBrush>
in here:
Same place, in the ControlTemplate of the control Style:
<Border CornerRadius="4">
<Border.Background>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<GeometryDrawing Brush="{StaticResource disable_glow}">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="0,0,1,1"/>
</GeometryDrawing.Geometry>
</GeometryDrawing>
...
When I use either StaticResource or DynamicResource keyword I get the same error.
So how to use it correctly?
You don't need to set the x:Name attribute on your LinearGradientBrush, if it's in a ResourceDictionary (i.e. a Resources collection). You just need to set x:Key to be able to access it.
The error you are getting would not be produced by the Brush="{StaticResource disable_glow}" code. If the resources wasn't found it would say something like "Resource not found". It sounds like you are/were trying to access it by name.
You would need to ensure that your LinearGradientBrush is defined before your ControlTemplate.

Resources