Beginner’s Tutorial: 3D Line and Border Effects in XAML
This mini-tutorial might be for you if you’re having troubles finding the right line colors to achieve simple 3D effects like these:
The solution to this very problem is actually pretty simple, and it always takes the same three ingredients:
- A white line
- A black line
- Reduced opacity
Basically, to get an edged line on a green background, you don’t need to fiddle with different shades of green. Just use white and black lines and play with the opacity. Here’s the settings in Blend for one of the white lines in the above screenshot:
…and this is the corresponding XAML for the two vertical lines:
<Grid Background="Green"> <Path Stretch="Fill" Stroke="#5A000000" Margin="25,62,0,0" Width="1" Height="100" Data="M130,176 L130,303.03543"/> <Path Stretch="Fill" Stroke="#5AFFFFFF" Margin="26,62,0,0" Width="1" Height="100" Data="M130,176 L130,303.03543"/> </Grid>
Tip: Hiding Blend’s Handles
If you’re trying to format a line, Blend’s handles don’t help much, as the basically hide the whole content:
However – you can easily hide / show them by pressing the F9 button.
Tutorial: Creating a 3D Toggle Button Style
Another usage of white and black lines is a 3D effect for borders. Let’s put this to action and create a reusable style that can be applied to a ToggleButton control:
Rather than joining four lines for each button state, I’ll use two Border controls with the same dimensions for each state, taking advantage that the BorderThickness property can be set independently for every edge. Here’s the borders for the unchecked state:
<Grid x:Name="uncheckedState"> <Border BorderBrush="#49FFFFFF" BorderThickness="1,1,0,0"/> <Border BorderBrush="#49000000" BorderThickness="0,0,1,1"/> </Grid>
…and here’s the borders for the checked state. Note that its Visibility property of the surrounding grid is set to Collapsed in order to hide the borders:
<Grid x:Name="checkedState" Visibility="Collapsed"> <Border BorderBrush="#49000000" BorderThickness="1,1,0,0"/> <Border BorderBrush="#49FFFFFF" BorderThickness="0,0,1,1"/> </Grid>
I put these borders together in a simple style, which uses a trigger to switch the visibility of the two borders as soon as the IsChecked property of the ToggleButton changes:
<Style TargetType="{x:Type ToggleButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ToggleButton}"> <Grid x:Name="mainGrid" Margin="0,0,1,1"> <Grid x:Name="uncheckedState"> <Border BorderBrush="#49FFFFFF" BorderThickness="1,1,0,0"/> <Border BorderBrush="#49000000" BorderThickness="0,0,1,1"/> </Grid> <Grid x:Name="checkedState" Visibility="Collapsed"> <Border BorderBrush="#49000000" BorderThickness="1,1,0,0"/> <Border BorderBrush="#49FFFFFF" BorderThickness="0,0,1,1"/> </Grid> <!-- WPF needs a background to toggle IsChecked if the ContentPresenter does not fill the whole area --> <Border Background="#00000000" /> <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" /> </Grid> <!-- triggers toggle visual appearance --> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="True"> <Setter TargetName="checkedState" Property="Visibility" Value="Visible" /> <Setter TargetName="uncheckedState" Property="Visibility" Value="Collapsed" /> <Setter TargetName="mainGrid" Property="Margin" Value="1,1,0,0"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
With the style in place, you can easily declare a ToggleButton like this:
<ToggleButton Width="100" Height="24" Content="hello world" />