ControlTemplate use control property - c#

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

Related

How can I add something to my custom listbox?

I made a custom listbox but when I push the button show every language nothing is showing. How can I fix this. When I delete the listbox style it just works fine. It's all in C#.
I hope you can help me.
greetings
Elias
<ListBox x:Name="lsbResultaatTaal"
Foreground="Black"
FontSize="15"
Grid.Row="1"
Margin="528,56,0,0"
Height="450"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Width="233">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{d:SampleData ItemCount=5}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Style>
<Style TargetType="ListBox">
<Setter Property="Background" Value="Gray"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.Style>
<ListBox.Template>
<ControlTemplate TargetType="ListBox">
<Border Width="230" Height="450"
CornerRadius="9"
BorderThickness="1"
BorderBrush="Black"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</ListBox.Template>
</ListBox>
You can set style in resources
<Window.Resources>
<Style TargetType="{x:Type ListBox}">
<Setter Property="Background" Value="Gray" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Gray" />
<!--
Why you choose same background color when hover listbox
Maybe same color your background and foreground
-->
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
OR
Can you try below changes:
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center"
Content="{Binding YourProp}" />

WPF Override control background property

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>

IsMouseOver Not Triggering for Button

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>

WPF how to attach different style to last child

I've got a WrapPanel containing multiple Buttons.
All buttons have the same base style to define their basic appearance.
Every button has a visible border at the right side. But I want to use styles to remove the border of the last button.
I think its quite simple. WPF is new to me, so I want to understand it.
The solutions I find on the internet are for different cases. That solutions are all concerning ListBox or ItemContainer to style some list items by index.
I don't want to just add another style key to the last Button, because that's not dynamic, and the WrapPanel is dynamically populated with Buttons depending on the state of the application.
This is my code:
<Window.Resources>
<Style x:Key="lastTabStyle" TargetType="Button">
<Setter Property="BorderThickness" Value="0" />
</Style>
<Style x:Key="tabButton" TargetType="Button">
<Setter Property="Background" Value="#FF21588B" />
<Setter Property="BorderThickness" Value="0 0 1 0" />
<Setter Property="Foreground" Value="#fff" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" Padding="20 10 20 10">
<ContentPresenter HorizontalAlignment="left" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FF266095" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="tabButtonSelected" TargetType="Button">
<Setter Property="Background" Value="#FF3474B0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Background="{TemplateBinding Background}" Padding="10 8">
<ContentPresenter HorizontalAlignment="left" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
And the WrapPanel:
<WrapPanel VerticalAlignment="Bottom" x:Name="topTabs">
<Button Style="{StaticResource tabButton}">Button 1</Button>
<Button Style="{StaticResource tabButton}">Button 2</Button>
<Button Style="{StaticResource tabButton}">Button 3</Button>
</WrapPanel>
...But I want to use styles to remove the border of the last button.
Then the define another style and apply this to the last Button or simply set ("override") the BorderThickness property of the last Button:
<WrapPanel VerticalAlignment="Bottom" x:Name="topTabs">
<Button Style="{StaticResource tabButton}">Button 1</Button>
<Button Style="{StaticResource tabButton}">Button 2</Button>
<Button Style="{StaticResource tabButton}" BorderThickness="0">Button 3</Button>
</WrapPanel>
Local values take precedence over values set by styles: https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-property-value-precedence

Changed button control template and now mouseover wont work

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.

Categories