WPF: How to make a "pushlike" checkbox? - wpf

I would like to make a CheckBox that looks exactly like a button. My initial feeble attempt doesn't work at all.
<CheckBox x:Name="test">
Testing!
<CheckBox.Template>
<ControlTemplate>
<Button>
<ContentPresenter/>
</Button>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>
The ContentPresenter isn't working (the button is empty) and when the button is clicked, the IsChecked property does not toggle. Also, I don't know how to make the button look pushed when IsChecked is true.

Would a ToggleButton suit your needs? CheckBox derives from it, and so they are very similar.

I've just started to write same comment :)
<ToggleButton Name="tb" Height="45" Width="45">
<ToggleButton.Style>
<Style TargetType="{x:Type ToggleButton}">
<Setter Property="Content" Value="False"/>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="True"/>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
And now as you wanted, Checkbox control:
<CheckBox>
<CheckBox.Template>
<ControlTemplate TargetType="CheckBox">
<ToggleButton x:Name="toggleButton">
</ToggleButton>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True" SourceName="toggleButton">
<Setter Property="Content" Value="True"/>
</Trigger>
<Trigger Property="Content" Value="True">
<Setter Property="IsChecked" Value="True"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</CheckBox.Template>
</CheckBox>

I agree that ToggleButton is the way to go, but if you want your content to show up in your example, try changing your ContentPresenter declaration to this:
<ContentPresenter Content="{TemplateBinding Content}" />

Related

Binding TextBlock color to Button IsEnabled from Style

I am trying to define a Style that could be used where Button holds a TextBlock as its Content and when Button has IsEnabled=False I want to set TextBlock's Foregroung color.
<Button Style="{StaticResource TransparentButtonStyle}"
IsEnabled="{Binding IsAllowed}">
<TextBlock Text="Click Me"
Style="{StaticResource HyperLinkStyle}">
</TextBlock>
</Button>
<Style x:Key="TransparentButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="Transparent">
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HyperLinkStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Foreground" Value="LightBlue" />
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>
Can I modify the TextBlock's Style to grab the parent Button's IsEnabled value somehow to be able to set the Foreground color ?
you can just add <Trigger Property="IsEnabled" Value="False"> to your HyperLinkStyle, but I recommend you to create LinkButtonStyle instead, so you final markup fill be much cleaner:
<Button Content="Link text" Style="{StaticResource LinkButtonStyle}" />
this just makes your views much cleaner...
here's my LinkButton template:
<Style x:Key="LinkButtonStyle" TargetType="Button">
<Setter Property="Foreground" Value="{StaticResource LinkButtonText}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock x:Name="ContentPresenter" Background="{TemplateBinding Background}"
Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="ContentPresenter" Property="Foreground" Value="{DynamicResource LinkButtonDisabled}" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsEnabled" Value="True" />
</MultiTrigger.Conditions>
<Setter TargetName="ContentPresenter" Property="TextDecorations" Value="Underline"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If you want to get to Button you can use DataTrigger with RalativeSource binding
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Setters -->
</Trigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Button}}, Path=IsEnabled}" Value="False">
<!-- Setters -->
</DataTrigger>
</Style.Triggers>
but if you want to make your Style independent of what is the parent then normal Trigger on IsEnabled property should work just as good
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<!-- Setters -->
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<!-- Setters -->
</Trigger>
</Style.Triggers>
normal Trigger should work because IsEnabled value is influenced by UIElement.IsEnabledCore which
Gets a value that becomes the return value of IsEnabled in derived classes
...
The default implementation of this property caches the value and also calculates whether the parent element of this element is enabled. (If the parent is not enabled, the child element cannot be effectively enabled in practical user interface (UI).)
so basically if parent Button is disabled child TextBlock will be disabled as well

WPF - Default Button Disable Style When Foreground applied

Button is applied with a Foreground when it is enabled. If it is Set as Disabled, default Button's Disabled Foreground need to apply.
<Button Width="150"
Height="50"
Content="Test"
Foreground="Red"
IsEnabled="False" />
I have Triggers for this button like
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
This Foreground is not applied when it is enabled.
Any idea on this?
Need like below,
If you set the properties locally the trigger will not be able to change the value due to precedence.
Move the Foreground and IsEnabled property into the style:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Button Width="150"
Height="50"
Content="Test">
</Button>
I am not sure I understand the question properly, because those codes posted in question should work fine. Following is a working sample to produce a Button exactly as the captured image shows. I put the Style as resource in the Button's container control -StackPanel in this case- :
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Button Width="150"
Height="50"
Content="Test"
IsEnabled="True">
</Button>
</StackPanel>
If you edit Button's default template you can find the following trigger inside control template.
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" TargetName="border" Value="#FFF4F4F4"/>
<Setter Property="BorderBrush" TargetName="border" Value="#FFADB2B5"/>
<Setter Property="TextElement.Foreground" TargetName="contentPresenter" Value="#FF838383"/>
</Trigger>
This trigger set Foreground to the content presenter using TargetName. No template binding used here. It directly assigns value. So the values you set for Foreground in Style Triggers will not be applied. You can edit the control template to achieve your requirement. This limitation not only for Foreground, for Background and BorderBrush also have this.
The following code is working for me:
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid x:Name="grid" Background="{StaticResource FlatButtonNavigation}">
<Border Name="ButtonBorder" CornerRadius="5,5,5,5"
BorderBrush="Gray" BorderThickness="2">
<ContentPresenter Name="MyContentPresenter"
HorizontalAlignment="center"
RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextBlock.FontSize="{TemplateBinding FontSize}"
TextBlock.Foreground="{StaticResource LeftPanelFontColor}"
Margin="10"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="ButtonBorder" Property="Background" Value="LightGray"/>
<Setter TargetName="ButtonBorder" Property="BorderBrush" Value="#FFADB2B5"/>
<Setter TargetName="MyContentPresenter" Property="TextBlock.Foreground" Value="White"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Can be worked using styles as mentioned in the other answers, but there is no need to go outside the button to define the style, you can define a style explicitly related to the particular button:
<Button Width="150" Height="50" Content="Test">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#FFADADAD"/>
</Trigger>
</Style.Triggers>
</Button.Style>
</Button>
</StackPanel>

WPF : How to style the initial state of a radiobutton group?

I just want to give an initial style to my radiobutton group, before one of the radiobuttons is checked or unchecked:
<Style x:Key="RadioButtonStyle" TargetType="{x:Type RadioButton}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Setter Property="Foreground" Value="Blue"/>
</Trigger>
<Trigger Property="IsChecked" Value="false">
<Setter Property="Foreground" Value="Green"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In this example, all my radiobuttons are unfortunately green, whereas I would like them to be red until the user clicks on one of them (at this point, the clicked button turns blue, and the others turn green).
How can i do that?
You just have to set the isChecked property for each RadioButton. Like this
<RadioButton GroupName="players" Grid.Column="2" Grid.Row="1" Name="hvP1" IsChecked="True"/>
<RadioButton GroupName="players" Grid.Column="2" Grid.Row="2" Name="hvP2" IsChecked="False"/>
...

WPF RadioButton Style using TextDecorations Underline

I would like to change the style of the WPF RadioButton so that the Bullet is not shown, the text is bold when IsSelected is true, the text is not bold, underlined, and the cursor is the hand when IsSelected is false. I have it almost working but I can not get the text underlined. This is my XAML so far.
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Foreground" Value="DarkBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border SnapsToDevicePixels="True">
<ContentPresenter VerticalAlighment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="TextBlock.FontWeight" Value="UltraBold" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Cursor" Value="Hand" />
<Setter Property="TextBlock.TextDecorations" Value="Underline" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Any suggestions anybody could offer that could explain why the text of the RadioButton is not underlined when IsSelected is False would be greatly appreciated.
Edit:
OK based on the link provided I was able to change the Style to the following.
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Foreground" Value="DarkBlue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<TextBlock x:Name="TextBlock" Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RadioButton}}, Path=Content}" />
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="TextBlock.FontWeight" Value="UltraBold" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Cursor" Value="Hand" />
<Setter TargetName="TextBlock" Property="TextDecorations" Value="Underline" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Then to use a RadioButton with this style.
<RadioButton Content"New" IsChecked="True" />
<RadioButton Content="Filter" />
This now shows two RadioButtons with no Bullet, its Content is Bold when IsSelected is true, and when IsSelected is false its not bold, underlined and shows the Hand cursor.
My only comment now is if I am Binding the Text Property of a TextBlock to the Content property of a RadioButton would that fail if the Content of the RadioButton is something other then a String?
Yes it will fail in the sense that the content will not be shown, instead you will get the result of ToString() on the content, but since you want underlined / bold text for your radio, that seems to be exactly what you want?

WPF: Can I Set IsMouseOver Property of a ChildElement When The Parent Is Moused Over?

Suppose I have a button nested in the Template of a ListBoxItem, can I set the IsMouseOver property of the button to true, so that it looks like its moused over?
Just for illustration, the notifications on the top of the window are what I am referring to. Its basically ListBoxItem's with a TextBlock and Button
Unfortunately, no. "IsMouseOver" is readonly.
I'm assuming, though, that you have a custom control template for the Button, right? If that's the case, one workaround is to mess with the Tag property of the button. Add a trigger to the ControlTemplate that gets fired when a specific Tag value is set. Then, in the DataTemplate for your ListBoxItems, just set the button's Tag to that specific value when IsMouseOver on the item is true. Below is an example:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel x:Name="dp" Background="Transparent">
<Button x:Name="btn" DockPanel.Dock="Right" Content="x" Background="Gainsboro">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="bd" Padding="2" BorderBrush="Black" BorderThickness="1"
Background="WhiteSmoke">
<ContentPresenter/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="bd" Property="Background" Value="LightBlue"/>
</Trigger>
<Trigger Property="Tag" Value="SimulatedMouseOver">
<Setter TargetName="bd" Property="Background" Value="LightBlue"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="bd" Property="Background" Value="Gray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock Text="{Binding}"/>
</DockPanel>
<DataTemplate.Triggers>
<Trigger SourceName="dp" Property="IsMouseOver" Value="True">
<Setter TargetName="btn" Property="Tag" Value="SimulatedMouseOver"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ListBox.ItemTemplate>
<s:String>Item1</s:String>
<s:String>Item2</s:String>
<s:String>Item3</s:String>
</ListBox>

Resources