Disclaimer, I'm at work and I don't have access to a platform I can test this code in, but from what I've looked up it should work.
The underlying problem is one of color blending, namely that we want to smoothly blend from full alpha to any arbitrary color. The problem with starting with Color.Transparent
is that you'll get a band of white while the alpha channel progresses more than the other components. A similar problem occurs with #00000000
as that has a band of black. The solution is to start with a version of your color that has the opacity set to 0
. How we go about this is slightly different based on which version of XAML based application you are developing--and I find it difficult to keep them straight. In UWP we don't have an opacity mask and we can't create a gradient on opacity alone. The only thing left is to use an IValueConverter.
The Color
property in GradientStop
is a Color
and not a Brush
, as that would overly complicate the rendering system. So the first step we need is an IValueConverter
that takes any Color
and strips out the alpha value:
public class TransparentColorConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, string language)
{
Color convert = (Color) value; // Color is a struct, so we cast
return Color.FromArgb(0, convert.R, convert.G, convert.B);
}
public object ConvertBack(object value, Type targetType,
object parameter, string language)
{
throw new NotImplementedException();
}
}
The next challenge is to create a binding that we can use this color against. The binding object allows us to specify a Source
, which can be any object we pass in. ElementName
won't work because resources are referenced by key, not name.
<LinearGradientBrush x:Key="OpacityGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="{Binding Source={StaticResource stdBackgroundColor},
Converter={StaticResource TransparentColorConverter}}" Offset="0"/>
<GradientStop Color="{StaticResource stdBackgroundColor}" Offset="1"/>
</LinearGradientBrush>
Of course, don't forget to put the TransparentColorConverter
in your Resources
so you can reference it here. Personally, I would prefer not to have to use converters, but in this case I think it is warranted.
NOTE: We use Source
in the binding so we can reference a static resource. If we had a property we could bind to, we could use a Path
instead.
The answer below is valid for WPF, but not UWP. I wish Microsoft would stop redefining the same concept in incompatible ways, but this is the world we live in.
Correcting my answer based on this answer
You want to change your LinearGradientBrush to use the Opacity property rather than the color #00000000
. The problem is that it is interpolating from basically black to your desired color. To get the affect you want you'll need to set up an opacity mask brush like this:
<LinearGradientBrush x:Key="OpacityGradientBrush" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#00FFFFFF" Offset="0"/>
<GradientStop Color="#FFFFFFFF" Offset="1"/>
</LinearGradientBrush>
Then in the code you need to apply the opacity mask to, you reference it like this:
<Grid VerticalAlignment="Bottom" Height="40" Grid.Row="3"
Background="{StaticResource stdBackgroundColor}"
OpacityMask="{StaticResource OpacityGradientBrush} Margin="0,0,0,-1"/>
The problem is that if you want the blend to only affect the opacity, the rest of the color has to be the same. You'll get a band of your starting color fading in and changing to the ending color otherwise.