How to create a WPF-tab control as chevron list? - wpf

I have a WPF tab control. but I would like to change the tab item style. The default style is square. I need to make it like a chevron list. Each block in that as hexagon.
EDIT:

Here's a quick example made with Kaxaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="chevronTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15"
Fill="{TemplateBinding Background}"/>
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Text="{TemplateBinding Header}" Margin="10,5" VerticalAlignment="Center" />
</Grid>
<Path Data="M0,0 10,15 0,30"
Fill="{TemplateBinding Background}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<TabControl ItemContainerStyle="{StaticResource chevronTabItemStyle}">
<TabItem Header="Design" Background="DarkSlateBlue" />
<TabItem Header="Plan" Background="DarkCyan" />
<TabItem Header="Build" Background="LightSkyBlue" />
<TabItem Header="Test" Background="SandyBrown" />
<TabItem Header="Evaluate" Background="SteelBlue" />
</TabControl>
</Grid>
</Page>
You will probably need to adjust a few properties, but it's roughly what you described...

Thomas Levesque your answer is beautiful!
There is a little problem with foreground color, move property into TextBlock prevent all tab to be colored White
In this way we can change the color of the header if properties IsEnable or Selected are valued.
<Style x:Key="TestNewTabStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15" Fill="{TemplateBinding Background}"/>
<Grid >
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Name="HeaderArrow" Text="{TemplateBinding Header}" Margin="15,5" VerticalAlignment="Center" Foreground="White"**/>
</Grid>
<Path Data="M0,0 10,15 0,30" Fill="{TemplateBinding Background}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderArrow" Property="FontWeight" Value="Bold" />
<Setter TargetName="HeaderArrow" Property="Foreground" Value="Yellow" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="HeaderArrow" Property="Foreground" Value="DarkGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

WPF styling tab items as arrow-like

I want to style my TabControl to have items similar to this:
I tried to the combination of Border (with right thickness of 0) and triangle shaped polygon with pushing the polygon out of bound a bit to overlap, but its not really working as the out of bounds part of polygon gets hidden. Here is my attempt and now I am stuck and don't really know what else to try:
<!-- Styles -->
<Style TargetType="{x:Type TabItem}">
<Setter Property="Padding" Value="15 0 15 0" />
<Setter Property="Background" Value="#f5f5f5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid ClipToBounds="False">
<Border x:Name="PART_Border"
Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
BorderThickness="1 1 0 1"
BorderBrush="LightGray">
<ContentPresenter ContentSource="Header" VerticalAlignment="Center" />
</Border>
<Polygon Points="0,0 20,25, 0,50"
Stroke="#e8e8e8"
Fill="#ffffff"
HorizontalAlignment="Right"
Margin="0 0 -10 0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="PART_Border" Property="Background" Value="#ffffff" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Content -->
<TabControl>
<TabItem Header="First" />
<TabItem Header="Second" />
<TabItem Header="Third" />
</TabControl>
This will do the job for you:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Background" Value="#f5f5f5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Path x:Name="Back" Data="M0,0 L 80,0 L100,20 L80,40 L0,40 L 20,20 " Stretch="None" VerticalAlignment="Stretch"
Stroke="#e8e8e8" StrokeThickness="2"
Fill="{TemplateBinding Background}"
HorizontalAlignment="Stretch" Margin="-30,0,0,0"/>
<ContentPresenter ContentSource="Header" VerticalAlignment="Center" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Back" Property="Fill" Value="#ffffff" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Instead of the border and polygon I used a Path to draw the shape for you.
You can use - (minus) values in margins to overlap items.
Result:

DatePicker template, borders appear on mouse over

I have a weird problem,
My DatePicker shows in the middle some borders. I don't know where it comes from.
I changed every property of the DatePickerTextBox but it doesn't change anything.
Here is the XAML :
<Window.Resources>
<Style TargetType="{x:Type DatePicker}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePicker}">
<Border x:Name="MainBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1" CornerRadius="5">
<Grid x:Name="PART_Root" Margin="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<DatePickerTextBox x:Name="PART_TextBox"
BorderThickness="0"
BorderBrush="Transparent"
HorizontalContentAlignment="Stretch"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="Center"
Visibility="Visible"
SelectionBrush="#FF6F5DF5"
FocusVisualStyle="{x:Null}"
Grid.Column="0" Margin="0,3,0,0">
<DatePickerTextBox.Style>
<Style>
<Setter Property="TextBox.BorderThickness" Value="0"/>
</Style>
</DatePickerTextBox.Style>
</DatePickerTextBox>
<Button x:Name="PART_Button" HorizontalAlignment="Right" Margin="0,0,0.333,0.333" Width="24">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Image Source="Resources/Images/down.png"></Image>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
<Popup x:Name="PART_Popup" StaysOpen="False" AllowsTransparency="True" Margin="0,0,0.333,0.333" />
<Label x:Name="lblLabel" Content="{TemplateBinding Uid}" HorizontalContentAlignment="Center" Foreground="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" BorderThickness="0" Padding="12,0" FontFamily="Poppins" VerticalContentAlignment="Stretch" Margin="6,-11,0,0" HorizontalAlignment="Left" VerticalAlignment="Top"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsDropDownOpen" Value="True">
<Setter TargetName="MainBorder" Property="BorderBrush" Value="#FF6F5DF5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="MainBorder" Property="BorderBrush" Value="#FF6F5DF5"/>
<Setter TargetName="PART_TextBox" Property="BorderThickness" Value="0"/>
<Setter Property = "BorderBrush" Value="{Binding ToYourBorder}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<DatePicker Margin="10,260,0,0" VerticalAlignment="Top" Uid="Date de naissance *" FontSize="12" Height="40" BorderThickness="0" HorizontalAlignment="Left" Width="181" FontFamily="Poppins" Background="#FFFEFEFE" BorderBrush="#FF9A9A9A" Foreground="#FF727272" />
And here how it seems :
And on hover, there is another thin border inside :
Any idea, please?
DatePickerTextBox has it's own Template where the border and the triggers for the border are defined/hardcoded.
You need to take care of those in the template of DatePickerTextBox.
Change:
<DatePickerTextBox.Style>
<Style>
<Setter Property="TextBox.BorderThickness" Value="0"/>
</Style>
</DatePickerTextBox.Style>
To:
<DatePickerTextBox.Style>
<Style TargetType="{x:Type DatePickerTextBox}">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<TextBox x:Name="PART_TextBox" BorderThickness="0"
Text="{Binding Path=SelectedDate, RelativeSource={RelativeSource AncestorType={x:Type DatePicker}}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DatePickerTextBox.Style>
And it should work.
For a complete Template see DOCS

WPF Button style with Image

I want to create a style for button with different images inside. I try to do following:
<Style TargetType="Button"
x:Key="PaintButton">
<Setter Property="Width"
Value="40"></Setter>
<Setter Property="Height"
Value="40"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border CornerRadius="3"
BorderThickness="2"
BorderBrush="Green">
<Image Source="{TemplateBinding Button.Content}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and try to use:
<Button Content="images/pen.png"
HorizontalAlignment="Left"
Style="{DynamicResource PaintButton}" />
but images is not shown. Why and how to do it correctly?
The "Image" is not a correct source for another Image.
Either use BitmapImage as Button's contents or use ContentPresenter in the template.
Option 1.
<Button Style="{StaticResource PaintButton}">
<BitmapImage UriSource="Back_Forward.png"/>
</Button>
Option 2.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border CornerRadius="3"
BorderThickness="2"
BorderBrush="Green">
<ContentPresenter Content="{TemplateBinding Button.Content}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Please try this
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Grid Height="30" Width="30" Background="{TemplateBinding Background}"/>
<TextBlock Text="{TemplateBinding Content}" TextAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Button Name="btnPrintCard" Margin="2" Content="Print Card">
<Button.Background>
<ImageBrush ImageSource="images/ic_print_black_48dp.png"/>
</Button.Background>
</Button>

WPF Template Binding Path.Fill

I have the following sytles:
<Style x:Key="WindowButtonTriggers" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource MainColorBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource MainColorBrush}" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="MinimizeButton" TargetType="Button" BasedOn="{StaticResource WindowButtonTriggers}">
<Setter Property="Background" Value="{StaticResource WhiteBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Canvas x:Name="appbar_minus" Width="48" Height="48" Clip="F1 M 0,0L 48,0L 48,48L 0,48L 0,0" Background="Transparent" UseLayoutRounding="False">
<Rectangle Width="24" Height="4" Canvas.Left="12" Canvas.Top="24" Stretch="Fill" Fill="{TemplateBinding Background}" />
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CloseButton" TargetType="Button" BasedOn="{StaticResource WindowButtonTriggers}">
<Setter Property="Background" Value="{StaticResource WhiteBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Canvas x:Name="appbar_close" Width="48" Height="48" Clip="F1 M 0,0L 48,0L 48,48L 0,48L 0,0" Background="Transparent">
<Path Width="20" Height="20" Canvas.Left="14" Canvas.Top="14" Stretch="Fill" Fill="{TemplateBinding Background}" Data="F1 M 17,14L 24,21L 30.9999,14.0001L 33.9999,17.0001L 27,24L 33.9999,31L 31,34L 24,27L 17,34L 14,31L 21,24L 14,17L 17,14 Z "/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When I create a button with the style "MinimizeButton" it works fine (when the mouse is over the button color changes) but when I create a button with the style "CloseButton" it doesn't work and I don't understand why since they are almost the same style.
Any help is greatly appreciated
Edit
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<my:Menu Grid.Column="0" BorderThickness="0,0,1,0" BorderBrush="#FF777777"/>
<WrapPanel Grid.Column="1" VerticalAlignment="Center" Margin="4,0,0,0">
<Button Style="{StaticResource MinimizeButton}" />
<Button Style="{StaticResource CloseButton}" Command="Close" />
</WrapPanel>
</Grid>
The reason that it is not working is because the Close command and CanExcecute is not defined which then sets the IsEnabled property on the button to false. MSDN states that
There is not necessarily an implementation for the command on any given object; in many cases the implementation for the command is the responsibility of the application writer.
Here is a good article on Code Project to get you started on working with WPF Commands.

wpf mouseover fill rectangle

I have Grid in wpf. When I do mouseover on rectangle, I can see color change. But when I do mouseover on content, I see original color of rectangle.
What should I write to apply same mouseover effect on ContentPresenter or is there any way to change rectangle background color on mouse over of content presenter.
<Grid Background="{TemplateBinding Background}" x:Name="dgColumnHeader">
<Border x:Name="border" BorderBrush="Black" BorderThickness="0,0,1,1" Grid.ColumnSpan="1">
<Rectangle Width="116" Margin="3,3,3,3" HorizontalAlignment="Center" RadiusX="7" RadiusY="7">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{DynamicResource ContentOutofFocusBrush}"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="{DynamicResource ActiveItemBrush}" />
</Trigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Border>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" />
</Grid>
Thanks
Dee
If the grid is part of your control template then it is better to move the rectangle style trigger into ControlTemplate.Triggers:
<Window x:Class="Presentation2.MouseOverRectangleWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MouseOverRectangleWindow" Height="300" Width="300">
<Window.Resources>
<SolidColorBrush x:Key="ContentOutofFocusBrush" Color="Orange"/>
<SolidColorBrush x:Key="ActiveItemBrush" Color="Blue" />
<Style x:Key="MouseOverContentControlStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Grid Background="{TemplateBinding Background}" x:Name="dgColumnHeader">
<Border x:Name="border" BorderBrush="Black" BorderThickness="0,0,1,1" Grid.ColumnSpan="1">
<Rectangle x:Name="PART_Rectangle" Width="116" Margin="3,3,3,3" HorizontalAlignment="Center" RadiusX="7" RadiusY="7">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Setter Property="Fill" Value="{DynamicResource ContentOutofFocusBrush}"></Setter>
</Style>
</Rectangle.Style>
</Rectangle>
</Border>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Rectangle" Property="Fill" Value="{DynamicResource ActiveItemBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<ContentControl Style="{StaticResource MouseOverContentControlStyle}">
<TextBlock Text="Hello World!" />
</ContentControl>
</Grid>
</Window>
you don't need a rectangle inside your Border. Change the Background of the Border, you ll have same result. Then put the ContentPresenter inside that Border, and set the MouseOver handler on the Border, it should work fine.

Resources