Transparent system color in gradient (WPF) - wpf

How to achieve such effect in XAML:
<LinearGradientBrush x:Key="BrightSeparatorGradient" StartPoint="0.0, 0.5" EndPoint="1.0, 0.5">
<GradientStop Offset="0.0" Color="{StaticResource {x:Static SystemColors.ControlLightColorKey}}" /> <!-- But fully transparent -->
<GradientStop Offset="0.5" Color="{StaticResource {x:Static SystemColors.ControlLightColorKey}}" />
<GradientStop Offset="1.0" Color="{StaticResource {x:Static SystemColors.ControlLightColorKey}}" /> <!-- But fully transparent -->
</LinearGradientBrush>
I've tried to create two brushes with appropriate color and Opacity set, respectively, to 0.0 and 1.0, but the compiler refused to take Brush as a Color (what is quite logic, on a second thought :)).
Best regards -- Spook.

I would create a MarkupExtension that takes a Color and returns the Color with the specified opacity:
public class OpacityExtension : MarkupExtension
{
private readonly Color color;
public byte Opacity { get; set; } // defaults to 0, so you don't have
// to set it for the color to be transparent
public OpacityExtension(Color color)
{
this.color = color;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Color.FromArgb(Opacity, color.R, color.G, color.B);
}
}
And then you use it like so:
<LinearGradientBrush x:Key="BrightSeparatorGradient" StartPoint="0.0, 0.5" EndPoint="1.0, 0.5">
<GradientStop Offset="0" Color="{lcl:Opacity {StaticResource {x:Static SystemColors.ControlLightColorKey}}}" />
<GradientStop Offset=".5" Color="{StaticResource {x:Static SystemColors.ControlLightColorKey}}" />
<GradientStop Offset="1" Color="{lcl:Opacity {StaticResource {x:Static SystemColors.ControlLightColorKey}}}" />
</LinearGradientBrush>

Spook,
Why the following doesn't work for you?
<LinearGradientBrush x:Key="BrightSeparatorGradient" StartPoint="0.0, 0.5" EndPoint="1.0, 0.5">
<GradientStop Offset="0.0" Color="Transparent" />
<GradientStop Offset="0.5" Color="{StaticResource {x:Static SystemColors.ControlLightColorKey}}" />
<GradientStop Offset="1.0" Color="Transparent" />
</LinearGradientBrush>

Related

WPF Control OverrideMetadata: specify default value to come from resource

I would like to specify a resource as a default value for my control for the BorderBrushProperty. The reason being the brush is a LinearGradientBrush which I defined in XAML. So I'm looking for something like this in my static CTOR (3rd line):
static Gauge()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof (Gauge), new FrameworkPropertyMetadata(typeof (Gauge)));
BorderThicknessProperty.OverrideMetadata(typeof (Gauge), new FrameworkPropertyMetadata(new Thickness(16)));
BorderBrushProperty.OverrideMetadata(typeof (Gauge), new FrameworkPropertyMetadata("OuterFrameStroke"));
}
This is what my XAML looks like (in themes\generic.xaml):
<LinearGradientBrush x:Key="OuterFrameStroke" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF636060" Offset="1" />
<GradientStop Color="#FF5F5C5C" Offset="0" />
<GradientStop Color="#FFEEDEDE" Offset="0.35" />
<GradientStop Color="#FFA09595" Offset="0.705" />
</LinearGradientBrush>
Well, should have thought 2 seconds longer. Of course I can set this default property in my template
<Style TargetType="gauge:Gauge">
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AFD6" Offset="0.321" />
<GradientStop Color="#FF8399A9" Offset="0.674" />
<GradientStop Color="#FF718597" Offset="0.375" />
<GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>

Adding Constant to resources

I have a brush defined as a constant in code that I want to add to the resources tag of a DataGrid I have defined in XAML with a specific key.
How do I do this?
I need to add the existing brush with the key since Im overriding the look of a highlighted row:
<DataGrid.Resources>
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="#FFD6A4" Offset="0"/>
<GradientStop Color="#FFAB3F" Offset="1"/>
</LinearGradientBrush>
</DataGrid.Resources>
The brush I want to use without having to redefine it is:
public static class Colours
{
public static LinearGradientBrush HighlightedRow { get; private set; }
static Colours()
{
HighlightedRow = new LinearGradientBrush(Color.FromRgb(255, 214, 164), Color.FromRgb(255, 171, 63), 90);
}
}
You can do this in code behind:
myDataGrid.Resources.Add(SystemColors.HighlightBrushKey, Colours.HighlightedRow);
Or in XAML only:
If you had the two gradient stop colors as resources, then you could reference them dynamically in XAML.
<Color x:Key="Color1">#FFFF0000</Color>
<Color x:Key="Color2">#FFFF3300</Color>
<DataGrid.Resources>
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="{DynamicResource Color1}" Offset="0"/>
<GradientStop Color="{DynamicResource Color2}" Offset="1"/>
</LinearGradientBrush>
</DataGrid.Resources>

How to create an array of linear gradient brushes in xaml using static resource?

I am trying to create an array of gradient brushes in xaml but I would like to point each array element back to a static resource that is the gradient brush. So, far I've been unable to achieve this. Can someone provide guidance on how I might accomplish this?
I want to add them to an x:Array but point to the resource rather than having to re-define the brushes as I've had to do here. I use the brushes in several places in addition to an array of them so I only want to define the brushes once.
<LinearGradientBrush x:Key="OrangeLinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFF7941D" />
<GradientStop Offset="1" Color="#FFF26522" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="RedLinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#F26263" />
<GradientStop Offset="1" Color="#B80303" />
</LinearGradientBrush>
<x:Array x:Key="BrushArray" Type="LinearGradientBrush">
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#FFF7941D" />
<GradientStop Offset="1" Color="#FFF26522" />
</LinearGradientBrush>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Offset="0" Color="#F26263" />
<GradientStop Offset="1" Color="#B80303" />
</LinearGradientBrush>
</x:Array>
You may use StaticResourceExtensions:
<x:Array x:Key="BrushArray" Type="LinearGradientBrush">
<StaticResourceExtension ResourceKey="OrangeLinearGradientBrush"/>
<StaticResourceExtension ResourceKey="RedLinearGradientBrush"/>
</x:Array>

Create a HUE color bar

I'm creating a color picker and I am at a stage where I need to create a HUE color bar:
One way to create it would be through gradient stops in XAML. For example:
<Rectangle Width="50" Height="100">
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0.025" EndPoint="0.5,1" >
<GradientStop Color="#FFFF0000" />
<GradientStop Color="#FEFFFF00" Offset="0.15" />
<GradientStop Color="#FE00FF00" Offset="0.3" />
<GradientStop Color="#FE00FFFF" Offset="0.45" />
<GradientStop Color="#FE0000FF" Offset="0.6" />
<GradientStop Color="#FEFF00FF" Offset="0.85" />
<GradientStop Color="#FFFF0000" Offset="1" />
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
The above will generate:
However, I am not sure whether the stops are correct.
Is there a convention on how to generate such a bar? Any advice would be highly appreciated.
Best Regards,
Casey
It looks like your 2nd last stop is at a different interval (+0.25) to the previous ones (+0.15). You basically want the same gap between all stops to get the same effect (that colour bar is just a linear distribution).
Try this instead:
<Rectangle.Fill>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1.0" >
<GradientStop Color="#FFFF0000" />
<GradientStop Color="#FEFFFF00" Offset="0.167" />
<GradientStop Color="#FE00FF00" Offset="0.333" />
<GradientStop Color="#FE00FFFF" Offset="0.5" />
<GradientStop Color="#FE0000FF" Offset="0.667" />
<GradientStop Color="#FEFF00FF" Offset="0.833" />
<GradientStop Color="#FFFF0000" Offset="1.0" />
</LinearGradientBrush>
</Rectangle.Fill>
Which looks like:

Using a StaticResource SolidColorBrush to define the Gradient Stop Colors

I am creating some wpf resource dictionaries with all the styles for an application! I have a few LinearGradientBrushes, where the color is set directly in the LinearGradientBrush reference as GradientStops. However, I want to have a predefined set of colors that I can use a a reference for each GradientStop, so that changing the color scheme for the application is a matter of changing the values of the SolidColorBrushes:
<SolidColorBrush Color="#5A5A5A" x:Key="colorbrushMedium" />
<SolidColorBrush Color="#222222" x:Key="colorbrushDark" />
<LinearGradientBrush>
<GradientStop Color="{StaticResource colorbrushMedium}"/>
<GradientStop Color="{StaticResource colorbrushDark}" Offset="1"/>
</LinearGradientBrush>
With the code example above, I am getting the following error:
Cannot convert the value in attribute 'Color' to object of type 'System.Windows.Media.Color'. '#5A5A5A' is not a valid value for property 'Color'.
The line it refers to is the line where <GradientStop Color="{StaticResource colorbrushMedium}"/> is defined.
Any ideas?
Ok, I found the problem:
Using Color and not SolidColorBrush..
<Color x:Key="colorbrushMedium">#FF5A5A5A</Color>
<Color x:Key="colorbrushDark">#FF222222</Color>
<LinearGradientBrush>
<GradientStop Color="{StaticResource colorbrushMedium}"/>
<GradientStop Color="{StaticResource colorbrushDark}" Offset="1"/>
</LinearGradientBrush>
This seems to solve my problem!
Use Binding to reference the color both in SolidColorBrush and in LinearGradientBrush:
<SolidColorBrush x:Key="stop1" Color="#FF5A5A5A"/>
<SolidColorBrush x:Key="stop2" Color="#FF222222"/>
<LinearGradientBrush x:Key="gradient">
<GradientStop Color="{Binding Source={StaticResource stop1},Path=Color}" Offset="0"/>
<GradientStop Color="{Binding Source={StaticResource stop2},Path=Color}" Offset="1"/>
</LinearGradientBrush>

Resources