Create link lable style WPF - wpf

I created the following style:
<Style x:Key="LinkText" TargetType="{x:Type Label}">
<Setter Property="Label.FontFamily" Value="Verdana"/>
<Setter Property="Label.FontSize" Value="13"/>
<Setter Property="Label.Foreground" Value="Blue"/>
<Setter Property="TextBlock.TextDecorations" Value="Underline"/>
</Style>
But when I try to use it on some label the UnderLine is missing.
I wrote at my UserControl the next Label:
<Label Grid.Column="1" HorizontalAlignment="Right" Style="{StaticResource LinkText}">
<TextBlock>some text</TextBlock></Label>
I see all the style properties except the underLine propery
How can I create Label style with underline?

Try to use a TextBlock control instead of a Label control. It behaves more or less exactly the same and should allow you to underline the text.
The TextBlock.TextDecorations dependency property belongs to the TextBlock control so you must use it to underline text.

Related

Override property of custom style

I have Style that applies to all of the buttons of my application:
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="StatusButtonCircle" Stroke="Black" StrokeThickness="0" Fill="AliceBlue" Stretch="Uniform">
<Ellipse.Width>
<Binding ElementName="StatusButtonCircle" Path="ActualHeight"/>
</Ellipse.Width>
</Ellipse>
<Ellipse x:Name="StatusButtonCircleHighlight" Margin="4" Stroke="Black" StrokeThickness="2" Stretch="Uniform">
<Ellipse.Width>
<Binding ElementName="StatusButtonCircleHighlight" Path="ActualHeight"/>
</Ellipse.Width>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
... some Triggers here
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
How can I change properties (e.g. FontWeight, FontSize etc.) in XAML? I tried this:
<Button FontWeight="Bold" FontSize="30" Foreground="Red">
</Button>
In the designer-view, I see the changes. But during runtime those changes are not applied.
After some investigation, I also have a Style for all TextBlock like this:
<Style TargetType="{x:Type TextBlock}">
<Setter Property="FontSize" Value="16" />
<Setter Property="FontFamily" Value="Segoe UI Semibold" />
<Setter Property="Foreground" Value="White" />
</Style>
This Style seems to override the TextBlock that is used on the Button. I still can't change the Text Properties in XAML.
Here's what it looks like if I use the Styles above in an empty project:
In the designer, the changes are applied, during runtime the one from the TextBlock are applied. If I assign a x:Key to the TextBlock, it works fine. But then I have to assign this Style to every TextBlock used in the app manually.
You are facing typical style inheritance issue in wpf.
A control looks for its style at the point when it is being initalized. The way the controls look for their style is by moving upwards in logical tree and asking the logical parent if there is appropriate style for them stored in parent's resources dictionary.
In your case, you are using ContentPresenter in button as a default behaviour. and it is using TextBlock to represent text in button by default.
Therefore at the time of initialization, ContentPresenter finding TextBlock style and applying to represent content in button.
If you want to restrict ContentPresenter to look for the style then you have to bind a blank style to content presenter so that it will not look for any further style.
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Red" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse x:Name="StatusButtonCircle" Stroke="Black" StrokeThickness="0" Fill="AliceBlue" Stretch="Uniform">
<Ellipse.Width>
<Binding ElementName="StatusButtonCircle" Path="ActualHeight"/>
</Ellipse.Width>
</Ellipse>
<Ellipse x:Name="StatusButtonCircleHighlight" Margin="4" Stroke="Black" StrokeThickness="2" Stretch="Uniform">
<Ellipse.Width>
<Binding ElementName="StatusButtonCircleHighlight" Path="ActualHeight"/>
</Ellipse.Width>
</Ellipse>
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center">
<ContentPresenter.Resources>
<Style TargetType="TextBlock" BasedOn="{x:Null}"/>
<!-- Assigned Blank style here therefore it will not search for any further style-->
</ContentPresenter.Resources>
</ContentPresenter>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You can do it with the BasedOn. I show you an example.
<Window.Resources>
<Style TargetType="ToggleButton" BasedOn="{StaticResource DefToggleButton}">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Content" Value="Some Cool Stuff"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="More Stuff"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Here in my resources I have DefToggleButton, now in my xaml file I can set up any Property according to my need (which in this case is the FontWeight and Content Property).
I think if you remove the Template from your Style, then you can do what you want to do, like this:
<Window.Resources>
<Style TargetType="Button" x:Key="stBtn>
<Setter Property="Background" Value="Blue" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontFamily" Value="Segoe UI Semibold" />
</Style>
</Window.Resources>
The Template that you have says, that all Buttons should be shown as a Border with a ContentPresenter inside, which is not what you have asked.
Without the Template, you can define your Buttons like this:
<Button Content="Hi!" Style="{StaticResource stBtn}" Foreground="Red" >
Like this, you have a Blue Button with Red Foreground.
=================
Edit
So what if you define a Template, and use it in you style, like this?
Then, by TemplateBinding you can define that the Foreground and teh Content come later, when the Button is actually defined.
<Window.Resources>
<ControlTemplate x:Key="ctBtn" TargetType="{x:Type Button}">
<Label Background="Green" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"/>
</ControlTemplate>
<Style x:Key="stBtn2" TargetType="{x:Type Button}">
<Setter Property="Template"
Value="{StaticResource ctBtn}" />
</Style>
<Window.Resources>
Then by defining the Button:
<Button Content="Hi!" Style="{StaticResource stBtn2}" Foreground="Red" >
===============
Edit2
So the general idea is that you can define a TemplateBinding for the properties of the elements in your template. So for example,you have an Ellipse in your template:
<Ellipse Fill="{TemplateBinding BorderBrush}" />
This defines that the Fill property of your Ellipse comes from the BorderBrush of your Button (Assuming that the template is targeting a Button)
Accordingly, you can put a Label in your Template, and set a TemplateBinding for its Forground and FontWeight property.
<Label Foreground="{TemplateBinding Foreground}" />
First, for this issue to be reproduced, Styles need to be set within a ResourceDictionary which is then added to Application.Resources (precisellyTextBlock global style). Setting Styles within for example Window.Resources will not reproduce the issue.
Global TextBlock Style is applied to the TextBlock created by ConentPresenter
As noticed in the question, the issue is that the global (keyless) Style for TextBlock is applied to the TextBlock created by ContentPresenter when it concludes the content to display is a string. For some reason this doesn't happen when that Style is defined within Window.Resources. As it turns out, there is more to this than just "controls are looking for their styles within their parent's resources".
ControlTemplate is a boundary for elements not deriving from Control class
For TextBlock (which doesn't derive from Control class, but from UIElement) within ControlTemplate, it means that wpf will not look for it's implicit Style beyond it's templated parent. So it won't look for implicit Style within it's parent's resources, it will apply application level implicit Style found within Application.Resources.
This is by design (hardcoded into FrameworkElement if you will), and the reason is exactly to prevent issues like this one. Let's say you're creating a specific Button design (as you are) and you want all buttons in your application to use that design, even buttons within other ControlTemplates. Well, they can, as Button does derive from Control. On the other hand, you don't want all controls that use TextBlock to render text, to apply the implicit TextBlock Style. You will hit the same issue with ComboBox, Label... as they all use TextBlock, not just Button.
So the conclusion is: do not define global Style for elements which don't derive from Control class within Application.Resources, unless you are 100% sure that is what you want (move it to Window.Resources for example). Or, to quote a comment I found in source code for MahApps.Metro UI library: "never ever make a default Style for TextBlock in App.xaml!!!". You could use some solution to style the TextBlock within your Button's ControlTemplate, but then you'll have to do it for Label, ComboBox, etc... So, just don't.

WPF Stackpanel spacing between custom controls

how is it possible to get a space between some custom controls inside a stackpanel? I did it right before with a Textbox, Button, and so on, but i cannot do it with a custom control.
That's the code i've got so far
<Grid>
<StackPanel x:Name="spTasks" CanVerticallyScroll="True">
<StackPanel.Resources>
<Style TargetType="local:SmartTaskOverview">
<Setter Property="Margin" Value="50,50,50,50" />
</Style>
</StackPanel.Resources>
</StackPanel>
</Grid>
Thanks for your help
FrameworkElements and their sub-classes don't just look for a resource using the controls type, they use the value of DefaultStyleKey. It's common practice for most sub-classes of Control (and some other FrameworkElements) to override the default value of this dependency property in the static constructor to be the type of the control, but sub-classes of UserControl usually don't bother.
static Foo()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Foo), new FrameworkPropertyMetadata(typeof(Foor));
}
If you didn't do this in your SmartTaskOverview then it will be looking for its default style using typeof(UserControl) as the resource key and not typeof(SmartTaskOverview).
Note: The UserControl will require a control template to show its children, this is normally provided by the default style for UserControl but by changing the key it will find your default style instead. To resolve this, just base your style on the UserControl style.
<Style TargetType="local:SmartTaskOverview" BasedOn="{StaticResource {x:Type UserControl}}">
<Setter Property="Margin" Value="50,50,50,50" />
</Style>
Alternatively you could provide a simple template yourself.
<Style TargetType="local:SmartTaskOverview">
<Setter Property="Margin" Value="50,50,50,50" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:SmartTaskOverview}">
<ContentPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Trouble binding to a property of templatedparent to set the value inside of a style setter in wpf

My problem:
I haven't been able to figure out how I inside the 'Setter.Value' field of a setter for a property A in a style targeting a particular control can do a binding to a property B of that particualr control. More specifically I want to use the Foreground brush value on a graphical element inside the visual tree of the Content property of a Button. this will ensure that the graphical element always has the foreground color set for this button control.
What I try to achive:
I'm working on a WPF-application where I have three button controls:
DefaultButton
SpecialButton
ExtendedSpecialButton
The DefaultButton is where I define the style of buttons in the application through a style with a ControlTemplate.
The SpecialButton introduces a new property not supposed to be used for general buttons. This property will be represented by one visual state that I define through a style setter. Else from that it shall be identical in apperance to the DefaultButton.
I define the style of this SpecialButton by basing it on the style of the DefaultButton. In this style there is no ControlTemplate only a MultiTrigger-response on the basis of a couple of property conditions setting av a couple of visual properties:
<Style x:Key="SpecialButtonStyle" TargetType="{x:Type MyControls:SpecialButton}" BasedOn="{StaticResource DefaultButtonStyle}">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsActive" Value="false"/>
<Condition Property="IsMouseOver" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="BorderBrush" Value="{DynamicResource ButtonDisabledBorder}" />
<Setter Property="Background" Value="{DynamicResource ButtonDisabledBg}" />
</MultiTrigger>
</Style.Triggers>
</Style>
All this worked great.
The next step is also no problem:
I wanted to base the ExtendedSpecialButton on the SpecialButton and set a default shape content inside the button.
<Style x:Key="ExtendedSpecialButtonStyle" TargetType="{x:Type MyControls:ExtendedSpecialButton}" BasedOn="{StaticResource SpecialButtonStyle}">
<Setter Property="Content">
<Setter.Value>
<Rectangle Fill="Black" Height="5" Width="15"></Rectangle>
</Setter.Value>
</Setter>
</Style>
The original style of DefaultButton is still present - the added visual state responding to the IsActiveProperty of the SpecialButton is still with us - and the ExtendedSpecialButton also inherited the visual behaviour created by the MultiTrigger of the SpecialButton.
I also successfully displayed a graphical element that this ExtendedSpecialButton should have.
However I wanted the fill of this graphical element to use the Foreground color. This foreground color is originally styled in the DefaultButton and works just fine for the two first buttons.
The code below is how I currently thought such a binding should be done. But this does not work:
<Style x:Key="ExtendedSpecialButtonStyle" TargetType="{x:Type MyControls:ExtendedSpecialButton}" BasedOn="{StaticResource SpecialButtonStyle}">
<Setter Property="Content">
<Setter.Value>
<Rectangle Fill="{Binding RelativeSource={RelativeSource TemplatedParent}}" Height="6" Width="20"></Rectangle>
</Setter.Value>
</Setter>
</Style>
Does anyone know what I could do to set up the binding so that it does what I intended it to do?

Resource Dictionary WPF

I have a resource dictionary in my WPF application which contains the style information for the various controls.
Can it be used like the way we use in CSS in HTML? For example
p
{
margin:20px;
font:Tahoma;
}
this applies to all "p" tags in HTML. We dont have to specifically mention that in the HTML for "p" tag.
Is the same approach applicable in WPF, or do we have to specifically
mention the style
<TextBlock Text="Test" Style="{DynamicResource SomeTextblockStyle}" />
in the XAML
You can certainly set a default style for each type. You can do this within your Generic.xaml, note that I am not providing a key.
<Style TargetType="{x:Type Button}">
<Setter Property="Height" Value="25"/>
<Setter Property="Foreground" Value="White"/>
</Style>
This will style every instance of a Button within your application as such.
If you were go to a XAML file and define an instance of a Button, overriding the Foreground value, that local instance will take precedence over the global style.
<Button Foreground="Black"/>
You can set style like using key
<Style TargetType="{x:Type TextBlock}" x:Key="myStyle">
<Setter Property="Margin" Value="20"/>
<Setter Property="FontFamily" Value="Tahoma"/>
</Style>
And in the Window.Xaml
<TextBlock Text="Hello" Style="{DynamicResource myStyle}"/>

How do I specify common layout markup or rules for controls in XAML?

I'm a WCF newbie, and I wonder, is it possible to declare in XAML that all my TextBoxes should have a height of 26, for example? That is, not to set the height of each item individually?
You need to define a style for your textbox
This will style the textbox when required
<Style x:Key="myTextBoxStyle">
<Setter Property="Height" Value="26" />
</Style>
<TextBox Text="Hi" Style="{StaticResource myTextBoxStyle}"/>
This will style all the textboxes
<Style TargetType="{x:Type TextBox}">
<Setter Property="Height" Value="26" />
</Style>
Put your Style into your resources block

Resources