I made a custom checkbox button with BorderThickness=2. I want to change the color of border to blue when it is checked.
Problem is there is very thin black line between border and the icon that annoys me. Is there any way that I can remove this?
Below is the partial code of my button style dictionary.
<Style x:Key="ExampleButton" TargetType="{x:Type CheckBox}">
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="40" />
<Setter Property="Background" Value="{StaticResource BrushDarkGray11}" />
<Setter Property="BorderBrush" Value="{StaticResource BrushDarkGray11}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Border x:Name="Grid" Background="{TemplateBinding Background}"
CornerRadius="2" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2">
<ContentPresenter x:Name="Content" Content="{TemplateBinding Content}"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Grid" Property="BorderBrush" Value="{StaticResource BrushBlue1}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It seems to be some kind of rendering artifact from WPF rendering the border with anti-aliased edges.
I was able to (mostly) get rid of it in my test code by telling WPF to render lines snapped to screen pixels by adding <Setter Property="SnapsToDevicePixels" Value="True" />
to the style (When I do any kind of desktop development, I always set this on the Window
anyway, as I think it makes WPF look cleaner). This looked better, but left a little pixel of a different color in each corner, most likely from the rounded corners.
Next, I tried nesting borders, like this:
<ControlTemplate TargetType="{x:Type CheckBox}">
<Border
x:Name="Grid"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="2"
CornerRadius="2">
<Border Background="{TemplateBinding Background}">
<ContentPresenter
x:Name="Content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</Border>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Grid" Property="BorderBrush" Value="{StaticResource BrushBlue1}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Which seems to have completely fixed it for me.
I just noticed that this covers up the inner corner radius. I kind of prefer this effect, but if it is a problem for your project, you can use a Grid
to overlay the borders, so that the rounded one draws on top. Make sure the rounded Border
has a transparent Background
. You will also need to set the Margin
on the background Border
to the same value as the BorderThickness
, or else this background will bleed through the outer corners of the Border
with rounded corners.
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid>
<Border Margin="2" Background="{TemplateBinding Background}">
<ContentPresenter
x:Name="Content"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}" />
</Border>
<Border
x:Name="Grid"
Background="Transparent"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="2"
CornerRadius="2" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Grid"
Property="BorderBrush"
Value="{StaticResource BrushBlue1}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>