I always thought I am stupid because I could never remember how to setup the LinearGradientBrush parameters properly. Until I spent a day writing a WPF application which allows me to see how the parameter settings look and I finally figured it is those parameters which are difficult to make sense of. If you want to understand them better, read this article.
Introduction
Have you ever encountered code like this and wondered what it does ?
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
This example is taken from https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.media.lineargradientbrush.
If you can answer the following questions, this article is not for you:
- What happens when you change '
0.5
' in StartPoint
and Endpoint
to the same, but different value? - What happens if you introduce another
GradientStop
with Offset -0.1
at the end? - What happens if
StartPoint
and Endpoint
have the same value?
However, if it surprises you that changing to two '0.5
' to any other value has no influence at all, then you should continue reading. :-)
Defining the GradientStops
First, you need to define the GradientStop
s. That is easy enough. The above code produces something like this:
However, you are surprisingly free when adding more GradientStops. For example, what happens when one more GradientStop gets added with offset 1 ?
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
<GradientStop Color="White" Offset="1.0" />
Nothing changed visibly. :-(
It seems if 2 GradientStop
s have the same offset, only the first is used.
What happens when a GradientStop
gets added out of sequence?
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
<GradientStop Color="White" Offset="0.5" />
It seems that the GradientStop
s get sorted by their offset. So even White
is defined last, it comes in the middle because of its offset. This sorting is a nice convenience feature.
What happens if values for offset 0 and 1 are missing ?
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
From 0 until the first colour defined at offset 0.25
, the color red is used. Similarly, after the last offset 0.75
, the same colour blue is used until offset 1
.
What happens if offsets smaller than 0
or greater than 1
are used?
<GradientStop Color="Yellow" Offset="-0.1" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.1" />
I thought this would generate an exception, but WPF accepts these values happily to define a gradient before 0 and after 1. For the LinearGradientBrush
, it uses only the colors defined between 0 (orange instead of yellow) and 1.
Defining the StartPoint and EndPoint
The GradientStop
s define the colours used in the gradient. The StartPoint
and EndPoint
define the direction of the gradient, like horizontally or vertically or any other angle. Strangely, this angle is not defined by an angle, but by 2 points, i.e., 4 coordinates.
In WPF, the point with the coordinates x=0 and y=0 is in the top left corner (in most graphics, it is in the left lower corner). LinearGradientBrush
supports two kinds of coordinates, per default with values from 0 to 1 and the resulting gradient is stretched to match the target. In the other mode, real screen coordinates are used. For simplicity, this article describes only the default settings.
Horizontal and Vertical Gradients
A StartPoint x=0, y=0 EndPoint x=1, y=0 defines a horizontal arrow from left to right (see upper square in sample 1) which then tells the LinearGradientBrush
to create a horizontal gradient with green left and blue right.
Sample 2 also has a horizontal arrow with the same direction, but this time, the arrow is at the bottom of the square. However, the result is exactly the same as in sample 1.
This explains why Microsoft LinearGradientBrush
help was so confusing to me. I wondered what the influence of 0.5
was, but couldn't figure it out. Now I know, for horizontal (and vertical) arrows, it doesn't matter where in the square the arrow is located.
Sample 3 shows a vertical gradient. The difference to the horizontal gradients is that 0 and 1 is in the y values and the x values (0.50 don't matter, as long they are the same.
Sample 4 is like sample 1, but this time the arrow runs from right to left, which switches blue to the left and green to the right.
Sample 5 shows the switched colors for a vertical gradient.
These samples show different vertical gradients. Sample 1 is the same as in the previous sample group.
In sample 2, the StartPoint
is at -0.2
, the arrow starts outside the square. The generated gradient is as long as the arrow, but the visible gradient shows only the part between 0 and 1. limegreen is at -0.2
. At 0, the gradient starts with a lighter limegreen, closer to white.
Sample 3 shows an arrow where the gradient only starts at 0.3. For the values 0 to 0.3, a constant limegreen is used.
Sample 4 shows an arrow starting and ending within the square. This can be quite useful so that the user can see more of the starting and ending color.
Sample 5 shows a combination of more starting color limegreen and a still light blue at the bottom, because the arrow goes below the square.
So far so good. But what happens if StartPoint
and EndPoint
have the same value?
I would have expected that sample 1 would be limegreen, because point 0 in the gradient is limegreen. However, it seems LinearGradientBrush
doesn't care about the points value and always takes the last gradient color. Strange indeed.
Slanted Gradients
Defining StartPoint
and EndPoint
in opposite corners of the square creates a diagonal gradient. The samples show the four possible variants.
The lengths of the diagonal arrows influence the gradients as already described. A bit strange is that sample 2 - 4 create exactly the same gradients, despite the arrows being in different locations. Stranger still, sample 5, which has the same arrow but again on a different location does produce a different gradient.
Having played around with gradients, I now have a bit of a feeling which arrow creates which gradients, but I cannot describe the behavior of the samples 2-5 with a few simple words. No wonder I felt it so confusing using LinearGradientBrush
in the past.
Sample Application Gradient Brush Explorer
Visual Studio tries to help with creating gradients and Blend has even a special gradient tool. Maybe it's just me, but with them I could never figure out how LinearGradientBrush
really works. So in half a day, I wrote a simple application where I can enter all the LinearGradientBrush
parameters and see the result immediately:
The grid has one line for each GradientStop
. Once all values are entered, press Execute and the gradient gets updated.
If you have read until here, you have shown a keen interest in WPF. I feel the topic of this article is rather boring, but I have written some truly interesting and helpful articles which I would like to recommend to you:
History
- 7th May, 2021: Initial version