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.