I have a style which underlines the textblock when it is mouseovered... How ever i need when it is clicked to change its font weight to bold(selected)..
any idea?
Code example of what dnr3 said, a templated ToggleButton
<Style x:Key="BoldWhenClickedTextBlock" TargetType="ToggleButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<TextBlock x:Name="c_toggleButtonTextBlock" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}, Path=Content}"/>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsMouseOver" Value="True">
<Setter TargetName="c_toggleButtonTextBlock" Property="TextDecorations" Value="Underline"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="c_toggleButtonTextBlock" Property="FontWeight" Value="Bold" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And then the "TextBlock" ToggleButton can use this with
<ToggleButton Style="{StaticResource BoldWhenClickedTextBlock}" Content="My Text.."/>
Related
I created a WPF TextBox with Placeholder text by creating a customized Style that overlays one TextBox (as a placholder text) on another TextBox in the ControlTemplate.
Here's the Style definition:
<Style x:Key="TextBoxFormBaseStyle"
BasedOn="{StaticResource {x:Type TextBox}}"
TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<TextBox x:Name="_textSource"
Panel.ZIndex="2"
Background="Transparent"
Text="{Binding Path=Text, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<TextBox x:Name="_textTag"
Panel.ZIndex="1"
Focusable="False"
Text="{TemplateBinding Tag}">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, Source={x:Reference _textSource}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, Source={x:Reference _textSource}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
<!-- Move Focus to child control -->
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="_textSource" Property="FocusManager.FocusedElement" Value="{Binding ElementName=_textSource}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
A Trigger on Property IsFocused allows focusing the the child TextBox control (named _textSource) when navigating through multiple TextBox's by Tab key.
Navigating to the previous element by pressing SHIFT + Tab is not working. How can I get SHIFT + Tab to set the focus to the previous element?
There are better ways to add a watermark if you want the TextBox to actuallty behave and get focused like a built-in TextBox. Try this style:
<Style x:Key="TextBoxFormBaseStyle" BasedOn="{StaticResource {x:Type TextBox}}" TargetType="{x:Type TextBox}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<Grid>
<TextBox x:Name="_textTag"
Focusable="False"
Text="{TemplateBinding Tag}"
BorderThickness="0">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Transparent" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Text, RelativeSource={RelativeSource AncestorType=TextBox}}" Value="">
<Setter Property="Foreground" Value="{Binding Path=OpacityMask, RelativeSource={RelativeSource AncestorType=TextBox}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Opacity" TargetName="border" Value="0.56"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF7EB4EA"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="BorderBrush" TargetName="border" Value="#FF569DE5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<TextBox OpacityMask="Red" Tag="Red Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
<TextBox OpacityMask="Green" Tag="Green Watermark" Text="text" Style="{StaticResource TextBoxFormBaseStyle}" />
I have a ToggleButton with a red background. I need to set a green background when the toggle button is checked.
I've tried this:
<ToggleButton Content="Test 001" Name="btn03" Height="20">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Background" Value="#ff0000" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#00ff00" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
But instead a green color I get a light blue color (I think is the default color of my
system).
What I'm doing wrong and how to fix it?
WPF 4.0 doesen't allow this. Look here for a different approach:
<Grid>
<Grid.Resources>
<Style x:Key="ToggleButtonStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="border" Background="Red">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Background" TargetName="border" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<ToggleButton Content="ToggleButton" Style="{StaticResource ToggleButtonStyle}"/>
</Grid>
Everywhere I've looked, I've found the standard solution to attach a ToolTip to a control whose Binding has Validation.HasError == true but nowhere shows how you might completely override the ToolTip's template so that you could, for example, still have your own custom theme which overrides the style for all ToolTips but when a control has that specific condition you can specify a template which has a red border, red see-through background and red text, for example.
The standard solution is:
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Does anyone know how to expand this to set the ToolTip background, border and text colour without overriding the base ToolTip control style? Bear in mind I've already specified this to create my own "theme" so I don't want to change it if possible.
Yes, you can do it like this:
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Content="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors).CurrentItem.ErrorContent}" Style="{StaticResource MyInheritedStyleForValidation}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Where MyInheritedStyleForValidation should probably override your theme style.
Set the DataContext of the ToolTip to the parent control:
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Foreground="White"
Background="Black"
DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}"
Content="{Binding Path=(Validation.Errors)[0].ErrorContent}"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
This fix the tooltip content.
<Style x:Key="{x:Type FrameworkElement}" TargetType="FrameworkElement">
<Setter Property="ToolTip" Value="{Binding GeneralTooltip}"/>
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationTemplate}"/>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip">
<Setter.Value>
<ToolTip Style="{StaticResource WarningTooltip}"/>
</Setter.Value>
</Setter>
<Setter Property="Tag" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</Style>
The tooltip template from his style:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToolTip}">
<!--Display the text-->
<Label Background="Transparent"
BorderThickness="0"
VerticalAlignment="Center"
Grid.Column="1"
Content="{Binding Tag, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Control}, AncestorLevel=2}}"
BorderBrush="Transparent"/>
</ControlTemplate>
</Setter.Value>
</Setter>
I am trying to create a WPF ToggleButton with a TextBox and a CheckBox as it's control template.
Here is what I have so far:
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="toggleButtonTextBlock"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}, Path=Content}"/>
<CheckBox x:Name="toggleButtonCheckBox" VerticalAlignment="Center" Margin="2"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}, Path=IsChecked, Mode=TwoWay}" >
</CheckBox>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="toggleButtonTextBlock" Property="TextDecorations" Value="Underline"/>
<Setter TargetName="toggleButtonCheckBox" Property="IsChecked" Value="True"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="False">
<Setter TargetName="toggleButtonTextBlock" Property="TextDecorations" Value="{x:Null}"/>
<Setter TargetName="toggleButtonCheckBox" Property="IsChecked" Value="False"/>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="{x:Null}">
<Setter TargetName="toggleButtonTextBlock" Property="TextDecorations" Value="{x:Null}"/>
<Setter TargetName="toggleButtonCheckBox" Property="IsChecked" Value="False"/>
</Trigger>
<Trigger Property="ToggleButton.IsMouseOver" Value="True">
<Setter TargetName="toggleButtonTextBlock" Property="TextDecorations" Value="Underline"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I click the Text of the ToggleButton, the text is properly underlined and the CheckBox is checked. But if I click the CheckBox, the text is not properly underlined (and the ToggleButton is not changed to IsChecked=True).
How do I get the ToggleButton to be IsChecked=True (and having the text underlined) when clicking the CheckBox?
It should be simple I guess, but being fairly inexperienced at XAML, this seems beyond my comprehension.
Thanks for your Help
You can simplify your triggers. In WPF, if the trigger evaluates to false then the target element/property will return to its previous state. Your binding on toggleButtonCheckBox is sufficient to set the IsChecked property on the ToggleButton; you don't need to set it in the trigger.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="toggleButtonTextBlock"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}, Path=Content}"/>
<CheckBox x:Name="toggleButtonCheckBox"
VerticalAlignment="Center"
Margin="2"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ToggleButton}}, Path=IsChecked, Mode=TwoWay}" >
</CheckBox>
</StackPanel>
<ControlTemplate.Triggers>
<!-- Will return to previous state if false -->
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="toggleButtonTextBlock"
Property="TextDecorations"
Value="Underline"/>
</Trigger>
<Trigger Property="ToggleButton.IsMouseOver" Value="True">
<Setter TargetName="toggleButtonTextBlock"
Property="TextDecorations"
Value="Underline"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
I need to change my Button background (as SolidColorBrush for example) only when it is not enabled (IsEnabled == false). How can I do?
Have I to modify the Button Style using the XAML or can I do this work programmatically? What is the correct XAML code, to change only the Background when it is not enabled?
I tried the following XAML code but it has no effect:
<Button>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
You can change the background by editing the template. You'll find the default template for Button here.
In the trigger for IsEnabled you can simply add something like this:
<Setter Property="Background" Value="{StaticResource DisabledBackgroundBrush}"/>
EDIT:
Try this instead then;
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="Overlay" CornerRadius="2">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="Overlay" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="Button" IsEnabled="False"/>
</StackPanel>
Just change it to suit your needs.
You can use a Style trigger:
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
<Setter Property="Image.Source" Value="pack://application:,,,/disabled.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>