XAML - Cannot add border thickness to button when style is applied - wpf

I am trying to add a border thickness to my first navigation button. Normally, you can easily add a BorderThickness to a button but when I add my own style it hides the BorderThickness and BorderBrush. I added a BorderThickness to the style (0,0,0,1) but am not able to have a border thickness of (0,1,0,0) to the first initial button. Any ideas?
<UserControl.Resources>
<Style x:Key="navButtStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border BorderThickness="0,0,0,1" BorderBrush="Black"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Button Style="{StaticResource navButtStyle}"
x:Name="navButton1"
Grid.Row="1"
Content="TR"
Background="#33333D"
FontFamily="Roboto"
FontSize="65"
FontWeight="Bold"
Foreground="White"
BorderBrush="Black"
BorderThickness="0,1,0,0"
HorizontalContentAlignment="Center"
ToolTip="navButton0"
Click="navButton1_Click"
/>
<Button Style="{StaticResource navButtStyle}" x:Name="navButton2" Grid.Row="2" Background="#33333D" ToolTip="navButton2">
<Grid>
<TextBlock Text="󰂯" Padding="30,30,0,0" FontSize="56" FontFamily="Material Design Icons Desktop" Foreground="White"/>
<TextBlock Text="󰖩" Padding="0,0,30,30" FontSize="56" FontFamily="Material Design Icons Desktop" Foreground="White"/>
</Grid>
</Button>
<Button Style="{StaticResource navButtStyle}" x:Name="navButton3" Grid.Row="3" Content="SL" Background="#33333D" FontFamily="Roboto" FontSize="65" FontWeight="Bold" Foreground="White" HorizontalContentAlignment="Center" ToolTip="navButton3" />
Navigation Buttons

property value hardcoded in Template cannot be easily changed from outside. use TemplateBindings instead:
<Style x:Key="navButtStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0,0,0,1"/>
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Related

WPF Progressbar style text

I have a style for a progressbar that shows some text only on the PART_Indicator section:
<Style x:Key="{x:Type ProgressBar}" TargetType="{x:Type ProgressBar}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ProgressBar}">
<Grid MinHeight="14" MinWidth="200">
<Border Name="PART_Track" CornerRadius="15" Background="{StaticResource PressedBrush}" BorderBrush="{StaticResource SolidBorderBrush}" BorderThickness="1" />
<Border Name="PART_Indicator" CornerRadius="15" Background="#CEAC2D" BorderBrush="#CEAC2D" BorderThickness="1" HorizontalAlignment="Left" >
<Viewbox>
<TextBlock TextAlignment="Center" Background="Transparent" FontFamily="Times" Foreground="Black" Margin="2,2,2,2"
Text="{Binding ProgressText}"/>
</Viewbox>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have a few bars and each one should show a different kind of text (50%, 2/8, etc..) and that of course is handled by the VM.
My question is how to use this style for all the bars but differentiate only that textblock text. I presume the binding is not correct .. I probably need a TemplateBinding, but to what property?

MouseOver style trigger won't change background

New to WPF, coming from a web background.
My style trigger won't change button background. Style XAML:
<Window.Resources>
<Style TargetType="Button">
<Setter Property="Background" Value="GhostWhite" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#F48230"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Button XAML (nothing relevant in Window or Grid attributes):
<Window...>
<Grid...>
<StackPanel Orientation="Horizontal" Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button Name="btnEdit" Cursor="Hand" Content="Edit Settings..." HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="0,0,5,0" Click="btnEdit_Click"/>
<Button Name="btnExit" Cursor="Hand" Content="Exit" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="5,0,0,0" Click="btnExit_Click" />
</StackPanel>
</Grid>
</Window>
The buttons do pick up the background style in the resources section, but not the trigger - mouseover results in default behaviour.
Supplementary question: Is there a way I can debug this? I looked in Live Visual Tree but couldn't figure out how to get the info I need.
WPF Controls have a Template property of type ControlTemplate. This property tells WPF how to draw the control on the screen. A WPF Button uses Windows Chrome in it's ControlTemplate which uses user selected system colors to allow for consistency between different applications. Leveraging the magic of WPF and XAML, you can create your own ControlTemplate to make the button look any way you see fit.
Create a style with a key so you can choose which buttons use the template:
<Window.Resources>
<Style x:Key="MyButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Background" Value="GhostWhite" />
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<!-- a simple square button -->
<Border Name="wrapper"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="{TemplateBinding Margin}"
Background="#01000000">
<!-- notice the wrapper has a background that is NEAR transparent. This is important. It'll ensure the button raises the click event -->
<Border Name=inner
Background="{TemplateBinding Background}">
<ContentPresenter Margin="{TemplateBinding Padding}"
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FFF48230"/>
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter Property="Background" Value="#FF99501B"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
And then to use the template on a button:
<Window...>
<Grid...>
<StackPanel Orientation="Horizontal" Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center">
<Button Style="{StaticResource MyButtonStyle}" Name="btnEdit" Cursor="Hand" Content="Edit Settings..." HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="0,0,5,0" Click="btnEdit_Click"/>
<Button Style="{StaticResource MyButtonStyle}" Name="btnExit" Cursor="Hand" Content="Exit" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Margin="5,0,0,0" Click="btnExit_Click" />
</StackPanel>
</Grid>
</Window>

Button Background property not working

I have a button with a style in my code. The Style is in the resources of the .xaml file:
<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="8" BorderBrush="#006AB6" BorderThickness="1" Name="border" >
<Grid x:Name="grid" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" ></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers></ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here's the code for the button:
<Button Name="btnZ" Background="Red" Content="{Binding Z}" Grid.Column="2" Style="{DynamicResource RoundCorner}" Visibility="{Binding Path=IsButtonVisible, Converter={StaticResource boolToVisibilityConverter}}"/>
The background property for the button, in which I set the property to Red - doesn't work. Why is that happening?
You have to map the Background of the Button to the Background of the inner ControlTemplate (whose the root visual is the Border) using TemplateBinding (for convenience):
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="8" BorderBrush="#006AB6" BorderThickness="1"
Name="border"
Background="{TemplateBinding Background}"
/>
<!-- ... -->
</ControlTemplate>

Changing font size of a button

In my .xaml file these are my resources:
<DataTemplate DataType="{x:Type vm:KeyModel}">
<TextBlock DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" FontFamily="Verdana" FontSize="26" Margin="0" >
<Run Text="{Binding Content.Text, Mode=OneWay}" />
</TextBlock>
</DataTemplate>
And here's the style:
<Style x:Key="RoundCorner" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="8" BorderBrush="#006AB6" BorderThickness="1" Name="border" Background="{TemplateBinding Background}">
<Grid x:Name="grid" >
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="18"/>
</Style>
And in code I have:
<Button Name="btn_Q" FontSize="8" Content="{Binding KB.Key_Q}" Grid.Column="1" Style="{DynamicResource RoundCorner}"/>
<Button Name="btn_A" Content="{Binding KB.Key_A}" Grid.Column="1" Style="{DynamicResource RoundCorner}"/>
But the FontSize for btn_Q doesn't get to be 8. How can I fix it? I need to make only btn_Q to have a fontsize of 8. All of my other buttons, like btn_A are fine with the style's fontsize.

WPF - Why is my buttons content moving separately from the button itself?

I have created a TabControl in a WPF application I'm writing. I re-templated TabItem so that I could have a button on each tab header to close it. So far, all is well and good.
I decided that I now wanted shiny round buttons instead of the default square ugly things. Also, I wanted to use an image as my buttons content instead of simply setting the content to "X".
My XAML styles/templates:
<Style TargetType="{x:Type Button}" x:Key="EllipseButtonStyle">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Ellipse Fill="{TemplateBinding Background}"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"/>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Button.Content}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ClosableTabItemTemplate">
<DockPanel MinWidth="120" Margin="0,0,0,0">
<ContentPresenter
Content="{Binding Path=DisplayName}"
VerticalAlignment="Center"
HorizontalAlignment="Left"/>
<Button
Command="{Binding Path=UnSubscribeApplicationCommand}"
CommandParameter="{Binding Path=DisplayName}"
BorderBrush="Black"
BorderThickness="2"
VerticalContentAlignment="Center"
VerticalAlignment="Center"
HorizontalAlignment="Right"
DockPanel.Dock="Right"
Width="16" Height="16">
<Image Source="closeicon.bmp" Height="8" Width="8"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Button.Style>
<Style TargetType="{x:Type Button}"
BasedOn="{StaticResource EllipseButtonStyle}">
<Setter Property="Background"
Value="{StaticResource CloseOffButtonBrush}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</DockPanel>
</DataTemplate>
With the above code in place, however, a selected tabs content (and the background as well) seems to shift upwards because of what I assume is the TabItems content moving upwards due to it being selected. Why, then, is the ellipse not shifting with the other content? Anyone have any idea what is going on here?
Sorry for the delayed response - I ended up solving the issue by modeling my TabItem template after the one posted in this blogpost. I believe the issue surfaced due to the fact that my TabItem template was being defined as a DataTemplate, not as a ControlTemplate as it should have been. Here is the new template:
<ControlTemplate x:Key="ClosableTabItemTemplate" TargetType="TabItem">
<Grid SnapsToDevicePixels="true">
<Border x:Name="Bd" Background="{StaticResource TabItemUnselectedBrush}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0" >
<DockPanel x:Name="ContentPanel">
<Button Command="{Binding Path=UnSubscribeApplicationCommand}" BorderBrush="Black" HorizontalAlignment="Center" Margin="3,0,3,0" VerticalAlignment="Center" Width="16" Height="16" DockPanel.Dock="Right" ToolTip="Close Tab">
<Button.Content>
<Image Source="pack://application:,,,/Resources/Close.png" Height="8" Width="8" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Button.Content>
<Button.Style>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource EllipseButtonStyle}">
<Setter Property="Background" Value="{StaticResource CloseOffButtonBrush}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource CloseOnButtonBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<ContentPresenter x:Name="Content" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{Binding Path=DisplayName}" RecognizesAccessKey="True" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
</DockPanel>
</Border>
</Grid>
<!-- bunch of ControlTemplate triggers to style the TabItem background color/position -->
</ControlTemplate>
Whenever I have controls inside a DockPanel, it always seems to play up if one of the controls I've explicitly attached DockPanel.Dock to comes AFTER the element I want to take up the fill portion. While I don't know if this will answer your question, try this instead in your ClosableTabItemTemplate DataTemplate:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ContentPresenter Grid.Column="0"/>
<Button Grid.Column="1"/>
</Grid>

Resources