Click here to Skip to main content
15,036,145 members
Articles / Desktop Programming / WPF
Article
Posted 7 May 2021

Tagged as

Stats

2.6K views
77 downloads
10 bookmarked

WPF LinearGradientBrush Parameters Demystified

Rate me:
Please Sign up or sign in to vote.
4.45/5 (4 votes)
7 May 2021CPOL5 min read
WPF LinearGradientBrush parameters are confusing and need a proper explanation
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 ?

XML
<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 GradientStops. That is easy enough. The above code produces something like this:

Image 1

However, you are surprisingly free when adding more GradientStops. For example, what happens when one more GradientStop gets added with offset 1 ?

XML
<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" />

Image 2

Nothing changed visibly. :-(

It seems if 2 GradientStops have the same offset, only the first is used.

What happens when a GradientStop gets added out of sequence?

XML
<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" />

Image 3

It seems that the GradientStops 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 ?

XML
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />

Image 4

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?

XML
<GradientStop Color="Yellow" Offset="-0.1" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.1" />

Image 5

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 GradientStops 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.

Image 6

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

Image 7

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.

Image 8

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?

Image 9

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

Image 10

Defining StartPoint and EndPoint in opposite corners of the square creates a diagonal gradient. The samples show the four possible variants.

Image 11

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: 

Image 12

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Peter Huber SG
Software Developer (Senior)
Singapore Singapore
Retired SW Developer from Switzerland living in Singapore

Interested in WPF projects.

Comments and Discussions

 
SuggestionYou missed a key point with the offsets... Pin
SledgeHammer017-May-21 4:34
MemberSledgeHammer017-May-21 4:34 
You pondered on what would happen if you used 2 stops with an offset of 1. Well, nothing obviously since 1 is the end of the gradient. Same as you wouldn't see anything if you had 2 stops with offsets at 0 since that's the start of the gradient.

Where using 2 stops with the same offsets comes into play is anywhere EXCEPT 0 and 1 Smile | :) . If you did something like:

Blue 0
Green 0.50

You'd get a nice smooth gradient. On the other hand, if you did something like:

Blue 0
Blue .50
Green .50

You'd instead get a hard transition between the 2 colors.

Also, why would 0.3,0 -> 0.3,1 vs. 0.5,0 -> 0.5,1 have any effect? You'd "theoretically" be shifting the gradient horizontally, but its a vertical gradient, so "no effect". Same thing if you change the vertical values on a horizontal gradient.


modified 7-May-21 14:18pm.

GeneralRe: You missed a key point with the offsets... Pin
Peter Huber SG13-May-21 0:32
MemberPeter Huber SG13-May-21 0:32 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.