I'm kind of new to WPF and I'm not really sure how the whole thing works. I have three buttons below, which I would like to be individually coloured. I also want them to be transparent and have grey text when they are disabled.
I want them to retain the Background colour property assigned in MainWindow.xaml when they are enabled and be transparent when disabled.
I'm not sure how I would go about this. Does it involve templates, styles, binding converters? Any help would be greatly appreciated.
MainWindow.xaml
<Button Grid.Column="0" Content="Suspend" Style="{StaticResource BubbleButton}" IsEnabled="True" Background="Blue"/>
<Button Grid.Column="1" Content="Training Mode" Style="{StaticResource BubbleButton}" IsEnabled="True" Background="Orange"/>
<Button Grid.Column="2" Content="Exit Program" Style="{StaticResource BubbleButton}" Background="Red"/>
App.xaml
<Style x:Key="BubbleButton" TargetType="{x:Type Button}">
<!-- Triggers -->
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Trigger.Setters>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="Gray"/>
</Trigger.Setters>
</Trigger>
</Style.Triggers>
<!-- Style -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="10" Background="{TemplateBinding Background}" Name="Button" Margin="10,5,10,5">
<Grid>
<Border BorderThickness="1,0,1,1" BorderBrush="Black" CornerRadius="{Binding ElementName=Button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="2" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<Border BorderThickness="0,1,0,0" BorderBrush="White" Margin="2" Opacity="0.7" CornerRadius="{Binding ElementName=Button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="2" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<TextBlock TextWrapping="WrapWithOverflow" Text="{TemplateBinding Content}" FontWeight="Medium" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="20" />
</Style>
Enabled:
Disabled:
using ControlTemplate.Triggers and adding TargetName should make it work. do the same for TextBlock and Foreground (from what I see, the Setter in Style, not in Trigger should be White).
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Button" Property="Background" Value="Transparent"/>
</Trigger>
</ControlTemplate.Triggers>
Related
The problem is IsMouseOver is not working when I hover the button, though I have customized the button and it is not working.
Can you say where is the error?
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border Height="22"
Margin="1"
VerticalAlignment="Center"
Background="White"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</cc:CustomFlatButton>
I have also checked if I use trigger Property="IsMouseOver". It is also not working. Where is the problem?
You have changed the Button Template and in this Template no property is bound to the Backgroud of the button.
In the trigger, you change the value of this property, but since no one uses this property, nothing changes in the display.
There are two main options to solve.
Set the Border's background binding to the Backgroud property of the button:
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border Height="22"
Margin="1"
VerticalAlignment="Center"
Background="{TemplateBinding Background}"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</cc:CustomFlatButton>
Or change the Border background with ControlTemplate triggers.
But this is applicable if CustomFlatButton is a Custom Control and not a UserControl.
That is, the CustomFlatButton should not have any predefined XAML.
<cc:CustomFlatButton Grid.Column="1"
Margin="1,0,5,4"
Command="{Binding ElementName=me, Path=Command疑い}"
CommandParameter="{Binding}"
IsEnabled="{Binding Path=疑いIsEnableFlag}">
<Run FontWeight="Bold">
疑い病名
</Run>
<Button.Style>
<Style TargetType="cc:CustomFlatButton">
<Setter Property="MinWidth" Value="80" />
<Setter Property="FontFamily" Value="メイリオ" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type cc:CustomFlatButton}">
<Border x:Name="PART_Border"
Height="22"
Margin="1"
VerticalAlignment="Center"
Background="White"
BorderBrush="#FFFF5656"
BorderThickness="2"
CornerRadius="6"
RenderOptions.BitmapScalingMode="NearestNeighbor"
TextOptions.TextFormattingMode="Display"
UseLayoutRounding="True">
<Label Padding="0,1,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
Foreground="Black" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="cc:CustomFlatButton.IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod" TargetName="PART_Border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</cc:CustomFlatButton>
I have the following style
<Style x:Key="RoundedBtn" TargetType="{x:Type Button}">
<Setter Property="Background" Value="White"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="button" CornerRadius="5" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Image x:Name="image" Source="{Binding ButtonImage, RelativeSource={RelativeSource AncestorType=Button}}" Margin="0,2,0,3" HorizontalAlignment="Left" Width="40" />
<Border BorderBrush="{x:Null}" Height="16" Margin="45,15,0,14" Width="123" HorizontalAlignment="Left">
<TextBlock x:Name="textBlock" Margin="-1" TextWrapping="Wrap" Text="{Binding ButtonText, RelativeSource={RelativeSource AncestorType=Button} }"
FontSize="13"
FontFamily="{DynamicResource Helvetica}" VerticalAlignment="Center" TextDecorations="{x:Null}">
</TextBlock>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="#8da0aa"></Setter>
<Setter Property="Foreground" Value="#318EE4"></Setter>
<Setter TargetName="textBlock" Property="TextBlock.TextDecorations" Value="Underline">
<!--That Text decoration part doesnt work--></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I apply this style to my "usercontrol" (which is actually a button):
<Button x:Name="btn" x:Class="MyStock.MyButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" Height="45" Width="183" Style="{DynamicResource RoundedBtn}" />
When I generate the project, the "MyButton" appears in my custom controls. But if I drag it on my form and test it, the Text Underline doesnt work.
But If i put a normal button on my form and then apply the RoundedBtn style, it works, why ?
By the way, what I am trying to achieve is to have a button that looks like the left menu buttons on this page
Use TargetName in the Setter:
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="textBlock" Property="TextBlock.TextDecorations" Value="Underline" />
</Trigger>
</ControlTemplate.Triggers>
The whole style looks like this (I remove irrelevant part for readability)
<Style x:Key="RoundedBtn" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="button">
<Grid>
<Border>
<TextBlock x:Name="textBlock" Margin="-1" TextWrapping="Wrap" Text="ABC"
FontSize="13" TextDecorations="{x:Null}">
</TextBlock>
</Border>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Setter TargetName="textBlock" Property="TextBlock.TextDecorations" Value="Underline" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
In my WPF application I want to to change borderbrush color for a TextBox when mouse enter, but it does not change color to the one I want, but it change to sky blue (I guess it is standard color).
Here is my XAML code:
<Window x:Class="OnePlayApp.Views.LoginDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OnePlayApp.Views"
WindowStyle="None"
ResizeMode="NoResize"
Title="LoginDialog" Height="350" Width="550" Foreground="Black">
<Grid Background="#282828">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24*"/>
<ColumnDefinition Width="43*"/>
<ColumnDefinition Width="43*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="59*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="50*"/>
<RowDefinition Height="191*"/>
</Grid.RowDefinitions>
<Image Margin="9,10,173,6" Source="/Resources/logo.png" Grid.ColumnSpan="2"/>
<Label x:Name="AccountName" Content="Account name" Margin="6,10,1,13" Foreground="#FFAFADAD" HorizontalContentAlignment="Right" Grid.Row="1"/>
<Label x:Name="Password" Content="Password
" Margin="6,10,1,13" Foreground="#FFAFADAD" HorizontalContentAlignment="Right" Grid.Row="2"/>
<TextBox x:Name="username" Margin="6,11,15,8" Background="#FF282828" Foreground="White" FontSize="15" Text="Ahsep12015#one.com" FontFamily="Yu Gothic UI Semibold" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2" VerticalContentAlignment="Center" BorderThickness="10">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="BorderBrush" Value="Green" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<PasswordBox x:Name="password" Margin="6,8,15,13" Background="#FF282828" Password="123456789" FontSize="18" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="2"/>
<Button x:Name="LoginBtn" Content="Login" Margin="6,15,15,146" Click="LoginBtn_Click" FontSize="16" FontFamily="Yu Gothic UI Semibold" Foreground="White" Grid.Column="1" Grid.Row="3">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#FFAFADAD"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#79B539"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="CancelBtn" Content="Cancel" Margin="6,15,15,146" Click="CancelBtn_Click" FontSize="16" FontFamily="Yu Gothic UI Semibold" Foreground="White" Grid.Column="2" Grid.Row="3">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="#FFAFADAD"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#79B539"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</Window>
I had the same issue on Windows 8, and the only way I was able to fix this issue (which appears to be a bug in WPF) was with a ControlTemplate. This is the standard control template for a TextBox as coughed up by Blend. I changed the BorderBrush colors, added it to my global TextBox style, and it works great. There may be a better solution out there, but this is what works for me.
<Style TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" Focusable="False" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
</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="Red"/>
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="BorderBrush" TargetName="border" Value="Orange"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Is it possible for the ControlTemplate to use a property from the control, that uses the template?
For example, I've got a button, that changes color to Red on MouseOver. But, I've also got a button, that looks exactly the same, except it changes to White, instead of Red. Would it be possible, that whatever Background value the Button has, that value is then used in the control template?
Currently, this is what my ControlTemplate looks like:
<ControlTemplate x:Key="CloseButtonTemplate" TargetType="{x:Type Button}">
<Border>
<Border.Style>
<Style>
<Setter Property="Border.Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="True">
<Setter Property="Border.Background" Value="#FFE53935" />
<Setter Property="Window.Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Foreground="#FFEEEEEE" HorizontalAlignment="Center" VerticalAlignment="Center" Text="X" FontFamily="Calibri" />
</Border>
</ControlTemplate>
What I'm trying to do, is have Border.Background set to whatever the Button Background value is. So if I have a <Button Background="Red" />, then the value of Border.Background is Red.
Yes It is possible for the ControlTemplate to use a property from the control, that uses the template.See this link for binding
<Window.Resources>
<ControlTemplate x:Key="CloseButtonTemplate" TargetType="{x:Type Button}">
<Border BorderBrush="Black" BorderThickness="1" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}">
<Border.Style>
<Style>
<Setter Property="Border.Background" Value="Transparent"/>
<Style.Triggers>
<Trigger Property="Border.IsMouseOver" Value="True">
<Setter Property="Border.Background" Value="{Binding Path=Background,RelativeSource={RelativeSource TemplatedParent}}" />
<Setter Property="Window.Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Foreground="#FFEEEEEE" HorizontalAlignment="Center" VerticalAlignment="Center" Text="X" FontFamily="Calibri" />
</Border>
</ControlTemplate>
</Window.Resources>
<UniformGrid>
<Button Background="Red" Template="{StaticResource CloseButtonTemplate}" Height="30" Width="200"/>
<Button Background="Green" Template="{StaticResource CloseButtonTemplate}" Height="30" Width="200"/>
<Button Background="Blue" Template="{StaticResource CloseButtonTemplate}" Height="30" Width="200"/>
</UniformGrid>
You should probably do this:
<Border x:Name="border" Background="{TemplateBinding Background}">
See TemplateBinding on MSDN
My button looks like this:
<Button ToolTip="Pending" Height="33" HorizontalAlignment="Right" Margin="0,5,379,0" Name="radButton2" VerticalAlignment="Top" Width="64" Background="#FF515151" BorderBrush="#FF515151" FontSize="14" Foreground="#FF5F5C5C" FontFamily="Mangal" Command="{Binding SetToPendingCommand}" IsEnabled="{Binding IsSetToPendingButtonEnabled}" Grid.Column="1" Grid.ColumnSpan="2">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="White" BorderThickness="1.5" CornerRadius="0">
<TextBlock Text="Pending" Foreground="White" TextAlignment="Center" FontSize="13" Margin="0,4, 0, 0" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
How do I get the mouseover to work correctly. I have tried not using a style and setting the template directly but that didnt't work either.
One way to do it is to move Triggers into ControlTemplate, give Border some name, for example x:Name="PART_Border", and then in the Setter you can specify TargetName="PART_Border":
<Button ...>
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="White" BorderThickness="1.5" CornerRadius="0" x:Name="PART_Border">
<TextBlock Text="Pending" Foreground="White" TextAlignment="Center" FontSize="13" Margin="0,4, 0, 0" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Red" TargetName="PART_Border"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
Move the trigger to ControlTemplate instead:
<ControlTemplate>
<Border BorderThickness="1.5" CornerRadius="0">
<TextBlock x:Name="txtBlock" Text="Pending" Foreground="White"
TextAlignment="Center" FontSize="13" Margin="0,4,0,0" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="txtBlock" Property="Background" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
All you need to do is add a template binding to the background property of the Border:
<Border Background="{TemplateBinding Background}" BorderBrush="White" BorderThickness="1.5" CornerRadius="0">
<TextBlock Text="Pending" Foreground="White" TextAlignment="Center" FontSize="13" Margin="0,4, 0, 0" />
</Border>
The important part is:
Background="{TemplateBinding Background}"
As it stands in the question the trigger is changing the template Background property, but that property is not being used within the control template.