how to change the style of a textblock in a button - wpf

I need to change the style of a textblock that it is inside a button..
here are my two styles:
<Style x:Key="btnStyleLR" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe UI Light" />
<Setter Property="FontSize" Value="40" />
<Setter Property="Padding" Value="0,20,0,20" />
</Style>
<Style x:Key="btnStyleLROverride" BasedOn="{StaticResource btnStyleLR}" TargetType="TextBlock">
<Setter Property="FontSize" Value="10" />
<Setter Property="Padding" Value="0,10,0,10" />
</Style>
and then:
<Style x:Key="btnLoginRegister" TargetType="Button">
<Setter Property="Width" Value="400" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="brd"
BorderBrush="Orange"
BorderThickness="1"
CornerRadius="6">
<TextBlock HorizontalAlignment="Center"
Style="{TemplateBinding Tag}"
Text="{TemplateBinding Content}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I bind the style in the tag property of the button pero it is not works.
then I have two buttons that I need to change de textblock style:
<Button x:Name="loginBtn"
Style="{StaticResource btnLoginRegister}"
Tag="btnStyleLROverride"
Content="Login" />
and the other:
<Button x:Name="registerBtn"
Content="Register"
Tag="btnStyleLR"
Style="{StaticResource btnLoginRegister}" />
is there another way to change the style with bind that works? thanks

You shouldn't destroy a button's template like that, unless it's only for the purpose of this question. The simple solution to your problem is to simply set the TextBlock as the button's content and then you can change its style without hacking through the templates.

In Tag you have to provide resource value, not string. It should be:
<Button x:Name="loginBtn"
Style="{StaticResource btnLoginRegister}"
Tag="{StaticResource btnStyleLROverride}"
Content="Login" />
Do it same way for other button.

As far as I understood your requirements:
You have two Buttons ("Login" and "Register") which need to be visually reduced (should not use visual states) and which have their own "text style" each (but maybe sharing a base style)? Is this correct?
If this is the case I recommend two different Button Styles (maybe sharing the same base style):
<Button x:Name="loginBtn" Content="Login"
Style="{StaticResource LoginButtonStyle}"/>
<Button x:Name="registerBtn" Content="Register"
Style="{StaticResource RegisterButtonStyle}"/>
And your styles:
<Style x:Key="PlainButtonStyle" TargetType="Button">
<Setter Property="FontFamily" Value="Segoe UI Light"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderBrush="Orange" BorderThickness="1" CornerRadius="6">
<TextBlock Text="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="LoginButtonStyle"
BasedOn="{StaticResource PlainButtonStyle}" TargetType="Button">
<Setter Property="FontSize" Value="10"/>
<Setter Property="Padding" Value="0,10,0,10"/>
</Style>
<Style x:Key="RegisterButtonStyle"
BasedOn="{StaticResource PlainButtonStyle}" TargetType="Button">
<Setter Property="FontSize" Value="40"/>
<Setter Property="Padding" Value="0,20,0,20"/>
</Style>
Properties like FontSize and FontFamily are inherited.

Related

In Wpf how to avoid/disable mouse hover a button highlight color?

I wonder if there is a way to do it for all the future buttons and other controls or do i need to make a solution for each control/button ? And how to do it ?
I want to disable the mouse hove highlight.
<Button x:Name="btnTest" Content="Start Watching" HorizontalAlignment="Left" Margin="14,241,0,0" VerticalAlignment="Top" Width="109" RenderTransformOrigin="0.484,-0.066" Height="30" FontSize="16" Background="#FFFB0000" Click="btnTest_Click"/>
<TextBox HorizontalAlignment="Left" Height="30" Margin="14,175,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="644"/>
<Button Content="Browse" Margin="673,175,18,0" VerticalAlignment="Top" RenderTransformOrigin="-0.111,0.769" Height="30" FontSize="16"/>
Add it to your ResourceDictionary:
<Style TargetType="Button">
<Setter Property="OverridesDefaultStyle" Value="True"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
BorderThickness="1"
Padding="4,2"
BorderBrush="DarkGray"
CornerRadius="3"
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And since Style has no key it will be on all the buttons
You'll need to create a style. if you want it to be applied through your whole app, you'll need to put it into your "app.xaml" file (within an application.Resources).
Bellow is an example of how to do it. I added some stuff like setters to illustrate that you can add properties, you could also add triggers and many things.
Not setting a "x:key" to your style will make them the default one (thus overriding the basic one), as the one below, if you wish to have a collection of styles, give them keys.
`<Style TargetType="{x:Type Button}">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderThickness"
Value="0" />
<Setter Property="Cursor"
Value="Hand" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center">
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>`

IsMouseOver Property on Button not working

I have this button and wanted to change the design if I hover over it with the mouse. It's not working and I'm not getting an error.
What am I doing wrong?
(I'm really new to WPF)
<Button MaxWidth="180"
Margin="5"
DockPanel.Dock="Top"
Padding="5"
FontSize="12"
Foreground="#1261AC"
FontWeight="SemiBold"
BorderBrush="Transparent">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="LightGray" BorderThickness="1" Padding="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#157ec4"/>
<Setter Property="Background" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
The button itself is working but it is not chaning the color of the background or font.
(The colors in my example are just for testing)
The problem with your code is that you define the border-background to be gray.
Now you change the control background using a trigger.
However, the background that is set by the trigger is not yet related to the border background in your example.
I added a template binding that fixes this issue to you. Now the border in your template will always have the Background defined in your style, set by triggers or directly set in XAML.
PLEASE NOTE:
If you set the color in XAML by using <Button Background="Pink"/> this will overwrite the style and trigger attributes.
if you still want to overwrite the background property for a single button for some reason without overwritting the triggers you'll have to create a style based on the original style using the BasedOn Property:
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Propert="Background" Value="Yellow"/>
</Style>
try this piece of art:
ButtonStyle:
<Button Content="Hello there!"
MaxWidth="180"
Margin="5"
DockPanel.Dock="Top"
Padding="5"
FontSize="12"
Foreground="#1261AC"
FontWeight="SemiBold"
BorderBrush="Transparent">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="HotPink"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="{TemplateBinding Background}" BorderThickness="1" Padding="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Background" Value="Lime" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>

WPF style present different while apply for multiply control

I have two button with the code in xaml is:
<Button Grid.Row="0" Grid.Column="2" Style="{StaticResource styleInfomationButton}" />
<Button Grid.Row="1" Grid.Column="2" Style="{StaticResource styleInfomationButton}" />
They're same style, but in runtime they were presented differently:
Here the image how the form showed:
Style applied:
<Style x:Key="styleInfomationButton" TargetType="Button">
<Setter Property="Width" Value="22" />
<Setter Property="Height" Value="22" />
<Setter Property="Content">
<Setter.Value>
<TextBlock FontWeight="ExtraBold" Foreground="White">?</TextBlock>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="20" Height="20">
<Ellipse Fill="#81A9F0" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When I tried the above code, it failed at runtime with the error:
Specified element is already the logical child of another element. Disconnect it first
Then, I looked at the code again and see you are setting Content property in the style. When you tried to apply the Style to two buttons, WPF tries to set the same TextBlock element as Content for the two buttons - this can't work. In WPF, for any element, you can only have one logical parent.
Update your style to the following, to get the desired behavior:
<Style x:Key="styleInfomationButton" TargetType="{x:Type Button}">
<Setter Property="Width" Value="22" />
<Setter Property="Height" Value="22" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Width="20" Height="20">
<Ellipse Fill="#81A9F0" />
<<TextBlock FontWeight="ExtraBold" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center">?</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Very good article on Understanding the Visual Tree and Logical Tree in WPF

Common Tooltip style in WPF

Can I make a tooltip style which can be applied to all tooltips for every control?
I tried this but I cant get the content (Tooltip text) in style, it is showing empty text in tooltip:
<Style TargetType="{x:Type ToolTip}" >
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Placement" Value="Bottom" />
<Setter Property="VerticalOffset" Value="0" />
<Setter Property="Padding" Value="8" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}" >
<StackPanel Margin="7,1" >
<Border Background="#FFF7F7CC" CornerRadius="1" >
<TextBlock Margin="1" Foreground="Black" HorizontalAlignment="Center" VerticalAlignment="Top" Text="{TemplateBinding ToolTip}"/>
</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For Using this style I have to put a seperate Tooltip tag in control, eg to apply tooltip to border,
<Border>
<Border.ToolTip>
<ToolTip ToolTip="This is tooltip text" />
</Border.ToolTip>
........
.........
</Border>
but is there any way where tooltipstyle applies to all control with tooltip mentioned in same tag.
eg.
<Border BorderBrush="Transparent" Background="Transparent" Cursor="Help" ToolTip="This is Tooltip" >
.....
.....
</Border>
let me know if any further details are required.
Thanks in Anticipation.
Yes Your approach will work. But a small change is needed in the Control Template. Replace the TextBlock with ContentPresenter.
<ControlTemplate TargetType="{x:Type ToolTip}" >
<StackPanel Margin="7,1" >
<Border Background="#FFF7F7CC" CornerRadius="1" >
<ContentPresenter Margin="1" HorizontalAlignment="Center" VerticalAlignment="Top" />
</Border>
</StackPanel>
</ControlTemplate>

How can I apply the same style for textbox and combobox in WPF?

I have made a BaseStyle, which looks like this:
<Style x:Key="BaseStyle" TargetType="{x:Type Control}">
<Setter Property="KeyboardNavigation.TabNavigation" Value="None" />
<Setter Property="AllowDrop" Value="true" />
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="FontFamily" Value="Segoe UI" />
<Setter Property="FontSize" Value="12" />
<Setter Property="Padding" Value="8,5,3,3" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Grid>
<Border x:Name="BorderBase" Background="White" BorderThickness="1,1,1.4,1.4" BorderBrush="Silver" CornerRadius="4" />
<Label x:Name="TextPrompt" Content="{TemplateBinding Tag}" Visibility="Collapsed" Focusable="False" Foreground="Silver"></Label>
<ScrollViewer Margin="0" x:Name="PART_ContentHost" Foreground="{DynamicResource OutsideFontColor}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="BorderThickness" TargetName="BorderBase" Value="1,1,2.4,2.4"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate x:Name="InspectorErrorTemplate">
<StackPanel Orientation="Vertical">
<Border BorderBrush="Red" BorderThickness="1" CornerRadius="4">
<AdornedElementPlaceholder Name="adornerPlaceholder"/>
</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And have used it this way to apply it to a textbox, which works fine:
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource BaseStyle}" />
Now I thought I can simply use the same style at a textbox of a combobox. So I thought I have to add something in this part:
<ControlTemplate x:Key="ComboBoxTextBox" TargetType="{x:Type TextBox}">
<Border x:Name="PART_ContentHost" Focusable="False" Background="{TemplateBinding Background}" />
<ControlTemplate.Triggers>
</ControlTemplate.Triggers>
</ControlTemplate>
However, I cannot add something like BasedOn="{StaticResource BaseStyle}" in the ControlTemplate to make e.g. the textbox to get a different border when it receives the focus (see IsFocused Trigger in the BaseStyle), or a red curved corner in case the validation is triggered... What am I doing wrong?
Hi you are working with different border color for different text-box that is the only problem here. There are several other options but I feel the following option is good to go.
You can create your own UserControl keeping a TextBox inside it. You can add a new DependencyProperty- BorderColor property in your UserControl. So that according to the BorderColor property value internally you can change the color of the border. So here you don't have to worry about multiple Style or any inheritance.
Isn't it?
The template for a TextBox is fundamentally different than the the template for a ComboBox. So you'll have to have different templates.
You can have one base style to define the shared properties (like Padding, FontFamily, etc.) without defining the Template property. Then make two more styles: one with TargetType set to TextBox; and the other with TargetType set to ComboBox. Each of these styles will be based on your base style and have additional definition for the template (and other properties that are not shared between the two controls).

Resources