WPF Gradient in 2 directions - wpf

If i want to make the edges of a selected item in a Listbox look smooth I do this:
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
<GradientStop Offset="0" Color="Transparent"/>
<GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
<GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
However, this only makes the left and right edge smooth, not the top and bottom. If I change StartPoint and EndPoint, I can make the top and bottom smooth, but then I loose the smoothness on the left&right sides. So how can I make all 4 borders smooth using a Gradient brush?

The OpacityMask is one way to do this, as others have already suggested, but it's slightly challenging because you cannot set an OpacityMask on a brush. You can only set it on a visual - OpacityMask is something that is done on a per-visual basis. But the Background of a ListBox isn't a separate element in the visual tree - it's just a property of the ListBox, and it's usually template bound to something like a Border element somewhere in the template.
Same goes for the use of bitmap effects that some people have suggested here - those are also applied to whole visuals, not to individual brushes.
However, you can handle this with a VisualBrush - that lets you define a brush by using a visual tree. So I think this does roughly what you're looking for:
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<VisualBrush>
<VisualBrush.Visual>
<Rectangle Width="1" Height="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0" StartPoint="1,0">
<GradientStop Offset="0" Color="Transparent"/>
<GradientStop Offset="0.05" Color="{x:Static SystemColors.HighlightColor}"/>
<GradientStop Offset="0.95" Color="{x:Static SystemColors.HighlightColor}"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Rectangle.Fill>
<Rectangle.OpacityMask>
<LinearGradientBrush EndPoint="0,0" StartPoint="0,1">
<GradientStop Offset="0" Color="Transparent"/>
<GradientStop Offset="0.05" Color="White"/>
<GradientStop Offset="0.95" Color="White"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Rectangle.OpacityMask>
</Rectangle>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
The corners might not be quite what you're looking for though - depends on how big they end up being. They don't look especially round when you use this technique. So you could go down the effect route. You might prefer this:
<Setter Property="Background" TargetName="Bd">
<Setter.Value>
<VisualBrush Viewbox="0.1,0.1,0.8,0.8">
<VisualBrush.Visual>
<Border Width="100" Height="100" CornerRadius="10"
Background="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}">
<Border.Effect>
<BlurEffect Radius="20"/>
</Border.Effect>
</Border>
</VisualBrush.Visual>
</VisualBrush>
</Setter.Value>
</Setter>
Note that I've used an Effect rather than a BitmapEffect. You have fewer options with Effect, but they're usually a better option as they're designed to render in hardware.

I don't think it can be done with the built-in gradient brushes. You could implement your own RectangleGradientBrush, but I don't think it's easy... (actually it doesn't seem possible, as Brush implementations depend on low level rendering stuff that's not accessible from user code)

Related

Wpf - Using Shapes as a Resource

Iv'e got a Rectangle in my resource dictionary which i would like to place inside numerous Grid objects
<Rectangle HorizontalAlignment="Left" Width="10" x:Key="ShadowRect">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1.7,0.603" StartPoint="0.3,0.603">
<GradientStop Color="White" Offset="1"/>
<GradientStop Color="Black" Offset="0.009"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
Now of course i could place it directly like so :
<Grid>
<Rectangle HorizontalAlignment="Left" Width="10" >
<Rectangle.Fill>
<LinearGradientBrush EndPoint="1.7,0.603" StartPoint="0.3,0.603">
<GradientStop Color="White" Offset="1"/>
<GradientStop Color="Black" Offset="0.009"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
but i would like to use it as a Resource so i do not have to write this XAML for every Grid ,
how can i place the rectangle using it's resource key ?
You could have a Rectangle Style instead of a Rectangle in your ResourceDictionary:
<Style x:Key="ShadowRectStyle" TargetType="Rectangle">
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Width" Value="10"/>
<Setter Property="Fill">
<Setter.Value>
<LinearGradientBrush EndPoint="1.7,0.603" StartPoint="0.3,0.603">
<GradientStop Color="White" Offset="1"/>
<GradientStop Color="Black" Offset="0.009"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
Then use it like this:
<Grid>
<Rectangle Style="{StaticResource ShadowRectStyle}"/>
</Grid>

Override Selected Item in Combobox's style to show comboxbox's background not gray background

I am having an issue with getting a custom property set with a combobox. I am using .Net 4.0, WPF with xaml resources for types set in a dictionary and some brushes set in the app.xaml. I can get the nice rounded corner just find and a gradient and layout to my combobox using the surrounding 'border' trick. However I can't seem to get the 'Selected Item' in the combobox to have a background other than dull gray. I would prefer to change it to transparent and inherit the gradient of the parent border. However I am missing the property or relationship to do this.
Does anyone know how to do this in the xaml?
Image:
code:
Dictionary item:
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource MoneyBrush}" />
<Setter Property="BorderBrush" Value="#071C07" />
<Setter Property="BorderThickness" Value="3" />
<Setter Property="CornerRadius" Value="20" />
<Setter Property="SnapsToDevicePixels" Value="True" />
</Style>
Brush in main App.xaml:
<LinearGradientBrush x:Key="MoneyBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#3A883A" Offset="1" />
<GradientStop Color="#FFFFFF" Offset="0" />
<GradientStop Color="#FF53AA75" Offset="0.50" />
<GradientStop Color="#073307" Offset="0.95" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="FontBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0" />
<GradientStop Color="#107810" Offset="0.50" />
<GradientStop Color="Black" Offset="0.65" />
</LinearGradientBrush>
Actual item in mainwindow:
<Border Margin="5" >
<ComboBox Height="30" Width="170" Margin="10" x:Name="combopersons"
FontSize="20"
ItemsSource="{Binding Path=People}"
DisplayMemberPath="FirstName"
SelectedValuePath="PersonId"
SelectedValue="{Binding Path=CurrentUser}"
Foreground="{StaticResource FontBrush}">
</ComboBox>
</Border>
EDIT >>>
I like the solution proposed by #iltzortz, but I wanted a gradient so in this case this would work better:
<ComboBox.Resources>
<LinearGradientBrush x:Key="{x:Static SystemColors.WindowBrushKey}" >
<GradientStop Color="#3A883A" Offset="1" />
<GradientStop Color="#FFFFFF" Offset="0" />
<GradientStop Color="#FF53AA75" Offset="0.50" />
<GradientStop Color="#073307" Offset="0.95" />
</LinearGradientBrush>
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" >
<GradientStop Color="#000000" Offset="1" />
<GradientStop Color="#FFFFFF" Offset="0" />
</LinearGradientBrush>
</ComboBox.Resources>
EDIT 2 >>>
For some reason this will only work on applications I have built using .NET 4.0 or higher on Visual Studio 2012 with Windows 7. When I try to run the code at home for some reason
it won't render I believe this is due to either Windows 8 or Visual Studio 2010 interpreting different colors for different system values. Be aware of this if you have Windows 8 or Visual Studio 2010 as it will work for me for one environment but not the other... curious.
The following code seems to do the job
<Grid Background="Pink">
<ComboBox Margin="10,0" Width="100" Height="40">
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
<ComboBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.WindowBrushKey}" Color="Green" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Green" />
</ComboBox.Resources>
</ComboBox>
<TextBox VerticalAlignment="Top" Margin="10"/>
</Grid>

How to create a bevelled gradient border in WPF

I'm trying to create a rounded end progress bar with a beveled border. I've got the progress bar looking like what I want but I'm having difficulty with making the border seemed beveled.
Can anyone help me out with this please?
An image of what I'm trying to get it to look like is here! Bevelled border
My current XAML code for the Window is as follows:
<Window x:Class="SplashDemo2.ProgressBarWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ProgressBarWindow" Height="100" Width="500">
<Window.Resources>
<Style x:Key="ProgressBarStyle" TargetType="ProgressBar">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ProgressBar">
<Border BorderBrush="#1D4276" BorderThickness="5"
CornerRadius="15" Padding="0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FFEAEAEA" Offset="0.9"/>
<GradientStop Color="#FF646464"/>
</LinearGradientBrush>
</Border.Background>
<Grid x:Name="PART_Track" >
<Rectangle x:Name="PART_Indicator"
HorizontalAlignment="Left"
RadiusX="10" RadiusY="10">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FF226494" Offset="0.9"/>
<GradientStop Color="#FFEBEFFA"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ProgressBar Value="50" Width="380" Height="25"
Style="{StaticResource ProgressBarStyle}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
</Window>
Can anyone help me to get the border looking like the image? Many thanks.
It looks to me as though the main thing you're missing is the gradient brush on the border itself.
If you omit BorderBrush="#1D4276" and instead include something like the below, you'll be a lot closer:
<Border.BorderBrush>
<LinearGradientBrush EndPoint="0.5,0.9" StartPoint="0.5,0">
<GradientStop Color="#FFEBEFFA" Offset="0.9"/>
<GradientStop Color="#FF226494"/>
</LinearGradientBrush>
</Border.BorderBrush>

silverlight styles

<navigation:Page.Resources>
<Style x:Key="PageBackground" TargetType="Grid">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Color="White" Offset="1"/>
<GradientStop Color="Silver"/>
</LinearGradientBrush>
<Path x:Name="shinePath" Data="M0,0 L0,300 C-5.5,306.5 40,68 215,0 z" Stretch="Fill" Opacity="0.1">
<Path.Fill>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0" SpreadMethod="Pad">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="#00FFFFFF" Offset="0.871"/>
</LinearGradientBrush>
</Path.Fill>
</Path>
</Setter.Value>
</Setter>
</Style>
</navigation:Page.Resources>
error- property 'Value' is set more then once
You've got a single <Setter.Value> element, it can contain only one child elment. Looks to me as though the Path is intended for a different property. Can't think what though Grid doesn't have a property that can accept a path. Do you intend the path to be the content of the Grid?

Using Styles in Windows Presentation Foundation

Imagine I have a data bound ListView and in the <ControlTemplate.Triggers>
I have the following
<DataTrigger Binding="{Binding Path=Status}" Value="Completed">
<Setter Property="Background" Value="{StaticResource CompletedBackground}" />
<Setter Property="Foreground" Value="Black" />
</DataTrigger>
I want that to be bound to a Style i have in my Grid.Resources which looks like the following:
<Style x:Key="CompletedBackground" TargetType="ListViewItem">
<Setter>
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBCFAA6" Offset="0"/>
<GradientStop Color="#FFA3E88B" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
However, as you might imagine this doesn't work, suprise suprise, you can't bind "Setter" to "Background", so my question is, how do I actually solve the problem?
I've looked through the following a lot of times, cant find any information here.
What you're trying to do is fundamentally flawed. For starters, your style's setter doesn't specify a target property. Presumably, the target property should be Background:
<Style x:Key="CompletedBackground" TargetType="ListViewItem">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBCFAA6" Offset="0"/>
<GradientStop Color="#FFA3E88B" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
Secondly, you're then trying to assign a Style instance to the Background property, which is of type Brush, not Style.
Depending on exactly what you're trying to achieve, you should be able to just change the Style to a Brush resource:
<LinearGradientBrush x:Key="CompletedBackground" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFBCFAA6" Offset="0"/>
<GradientStop Color="#FFA3E88B" Offset="1"/>
</LinearGradientBrush>
Then use it from your trigger in the same fashion you already are.

Resources