Changing Label colour through button template C# WPF - c#

In an attempt to use a Click event on a label I have found an example of using a button but applying a template to it so that it looks like a label. As shown below:
<Button Name="LooksLikeALabel" Canvas.Left="279" Canvas.Top="-37" Height="26" Width="48" Content="Words" Click="answer1Label_MouseUp" MouseEnter="answer1Label_MouseEnter" MouseLeave="answer1Label_MouseLeave">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Label x:Name="buttonLabel" Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Button.Template>
</Button>
Now I want to be able to change the colour of the text on mouse over. Changing the foreground on the button does nothing bot in the code behind and through the XAML. Changing the colour of the label foreground works through the XAML but for whatever reason I am unable to access the label through the code behind meaning I can't access any of the label controls through my C#.
Is there something I am missing to get control over the label in the code behind? Alternatively, is there a better way to have a click event on a label?

Put Trigger inside ControlTemplate of button:
<Button Name="LooksLikeALabel" Canvas.Left="279" Canvas.Top="-37" Height="26"
Width="48" Content="Words">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Label x:Name="buttonLabel" Content="{TemplateBinding Content}"/>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="buttonLabel" Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>

Related

WPF understand why textbox template into textblock still editable

In my project i have created a template for my textbox, for test purpose i simplify it to this code:
<Window.Resources>
<Style x:Key="test" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<TextBlock Text="{TemplateBinding Text}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<TextBox Style="{StaticResource test}" Grid.Row="2" Height="50" Width="200" Text="test">
</TextBox>
</Grid>
For what i understand, template erase how should be represented the textbox and show what i put in the template.
so when i put 'test' to the text TextBox, in reality it put it to the text Textbloc inside the textbox.
textbloc should be readonly, but on running if i clic on the label and tap on my keyboard, it still print key at the start of text (only add char at the start of text)...
(with binding it's editing the binding property...)
With a IsReadOnly="True" on the actual textbox it work as expected, but i don't understand why i need to do it.
I try on net6.0-windows and net5.0-windows, same result.
Is anymone understanding what i missing ?
Thank's for your time

Changing Button Background Programmatically not Working

I have a Stack Panel, that contains three buttons. When a button is clicked I want the background to stay permanently changed, however it doesn't seem to working.
I've tried to set the background colour programmatically as I've written below however it doesn't seem to work. When I set the foreground colour programmatically that works, changing the colours as instructed. I think as I'm using a template for the buttons in the XAML, where I assign a background colour, has priority over a programmatic change.
Attempt at changing background:
AColour.Background = Brushes.Black;
BColour.Background = Brushes.Red;
CColour.Background = Brushes.Black;
Attempt to change foreground (which works):
AColour.Foreground = Brushes.Black;
BColour.Foreground = Brushes.Red;
CColour.Foreground = Brushes.Black;
XAML (Button Template):
<Window.Resources>
<ControlTemplate x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Border Name="body" Background="#AEEEEE" BorderThickness="0" BorderBrush="DimGray" Padding="2">
<ContentPresenter HorizontalAlignment="Left" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="body" Value="#12CCD3"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" TargetName="body" Value="#009DA2"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
XAML Button Declaration (Same for all 3 buttons except name):
<Button Cursor="Hand" x:Name="AColour" Height="40" Template="{StaticResource ButtonStyle}" Width ="100" Click="A_Click">
Is there any way (if the template is having priority) to overwrite the template and change the background programmatically?
Because you have set button's background to "#AEEEEE" explicit, so ,the button's background will not changed by code.
I think you should use TemplateBinding in you Template,like this:
<Border Background="{TemplateBinding Background}">
<ContentPresenter ...... />
</Border>

Bind a custom property to a template in WPF

I want to create a template for a button, that will show an image (icon) instead of text.
I want to be able to assign different images to different instances of that button, for example:
<Button Style="{StaticResource iconButton}" ImageSource="Sources/icon.png">
or alternatively:
<Button Style="{StaticResource iconButton}">
<Image Source="...">
</Button>
(but I still want to be able to style the image in the template, so I wouldn't need to worry about color and size when I use it - so simply rendering the image as content won't do).
Example code:
Here I am using the image as a mask to render it in whatever color I want:
<Style TargetType="Button" x:Key="iconButton">
<Style.Resources>
<!-- add the "content to image source" converter-->
<converters:ContentToImageSourceConverter x:Key="ContentToImageSourceConverter"/>
</Style.Resources>
<Setter Property="Foreground" Value="{DynamicResource foreground_color}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid Margin="5">
<Ellipse x:Name="circle" Width="45" Height="45" Fill="{DynamicResource foreground_color}" Opacity="0"/>
<Ellipse Width="45" Height="45" Fill="{DynamicResource foreground_color}">
<Ellipse.OpacityMask>
<!--How to accomplish this?-->
<ImageBrush ImageSource="{TemplateBinding Property=Content "/>
</Ellipse.OpacityMask>
</Ellipse>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="circle" Property="Opacity" Value="0.15"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="circle" Property="Opacity" Value="0.3"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Have a look at the line where it says "how to accomplish this". I am using an image as a source but I want the image to be defined whenever you use the button, for example:
<Button Style="{StaticResource iconButton}" DockPanel.Dock="Right">
<Image Source="/Sources/settings_icon.png"/>
</Button>
I do not want to simply render the image as a content of the button because I'm using it as a mask for something else, thus I can change the foreground color and have the icons render in a different color.
I would do a custom control, with one dependency property of the image source. Have you tried this?
And then you will use it like this
<MyCustomButton DockPanel.Dock="Right" ImageSource = Sources/settings_icon.png">
</MyCustomButton>
The simplest way to do it:
Add UserControl to your project
In xaml just add one button
Add style to this control and set it to the button
Add dependency property, and link it to the image source (in style) by binding. Here you need also to have specified a source of binding.
{Binding RelativeSource={RelativeSource Self}}
Second way:
Make an class which is deriving form the Button class.
Add one dependency property, with the image source object.
In Style Specify a binding for the source property of the image control, it has to have the same name as he dependency property. I think that you will also need to specify the source of the binding as a Ancestor, because it could not be able to find the binding source.
Check here to see the syntax.
Binding to an ancestor in WPF
In both ways the usage will look same.

Is it possible to provide 'arguments' to Custom control Styles & Templates?

I have 2 buttons, both of which are using a style to keep a consistent UI. However for 1 button, I would like to provide an image for, and the other just text.
I suppose I could create a new style, copy everything over, and the reformat it to my liking, but this seems like waste, is time consuming, and i think i would have to do it for each instance I wish to have a image on a button. I mean, that's fine, but I just want to know if there is an alternative that would make things more elegant.
I think I should somehow be able to push an 'arguement' or data to a style, either in or out of XAML to format the style, or something that would accomplish this (I'm sure the terminology is wrong).
Here is the Button Style:
<Style x:Key="Control_Button" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image> <!-- Optional Image here --> </Image>
<TextBlock Name="btn" Text="{TemplateBinding Content}" Padding="16" VerticalAlignment="Center">
<TextBlock.TextDecorations>
<TextDecoration Location="Underline" />
</TextBlock.TextDecorations>
</TextBlock>
<!-- FIX ME: not underlined normally -->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="TextBlock.IsMouseOver" Value="True">
<Setter TargetName="btn" Property="TextDecorations" Value="none" />
<!-- FIX ME: underlined on hover -->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
What you are asking for is not possible without creating a custom control or user control.
What you should do though is setting the contents of the button the way you like. If you want only a string, you can set it directly:
<Button>my text</Button>
or with a binding:
<Button Content={Binding textProperty} />
To include an image in the button, add a panel as content, in this example I added a StackPanel, but you can also use a Grid or any other element:
<Button>
<Button.Content>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding myImagePath}" />
<TextBlock Text="{Binding myText}" />
</StackPanel>
</Button.Content>
</Button>

Reusable way to put a bright red box around whatever element currently has focus?

I've got some windows with mainly comboboxes, textboxes, and checkboxes. When you click on one to get focus I need a way to have them be outlined with a colorful box (boss' orders). Is there a way to do this easier than overriding the default style of all of these controls? I've never done that before, so it would take a lot of mucking around on my part to figure it out.
You can try adding a FocusVisualStyle to the Controls that need different focus rectangle styles.
From above link
The second mechanism is to provide a separate style as the value of the FocusVisualStyle property; the "focus visual style" creates a separate visual tree for an adorner that draws on top of the control, rather than changing the visual tree of the control or other UI element by replacing it.
Something like this in your Window's Xaml
<Window.Resources>
<Style x:Key="NewFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Stroke="Red" Margin="2" StrokeThickness="1" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
or your Application.Xaml file.
<Application.Resources>
<Style x:Key="NewFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Border>
<Rectangle Stroke="Red" Margin="2" StrokeThickness="1" StrokeDashArray="1 2" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
Usage:
<ComboBox FocusVisualStyle="{StaticResource NewFocusVisual}" Height="23" HorizontalAlignment="Left" Margin="238,102,0,0" Name="ComboBox1" VerticalAlignment="Top" Width="120" />
<CheckBox FocusVisualStyle="{StaticResource NewFocusVisual}" Content="CheckBox" Height="16" HorizontalAlignment="Left" Margin="238,71,0,0" Name="CheckBox2" VerticalAlignment="Top" />
<TextBox FocusVisualStyle="{StaticResource NewFocusVisual}" Height="23" HorizontalAlignment="Left" Margin="238,144,0,0" Name="TextBox1" VerticalAlignment="Top" Width="120" />
If you want the Focus rectangle to change for every type of focus event Microsoft states that:
From Microsoft: Focus visual styles act exclusively for keyboard focus. As such, focus visual styles are a type of accessibility feature. If you want UI changes for any type of focus, whether via mouse, keyboard, or programmatically, then you should not use focus visual styles, and should instead use setters and triggers in styles or templates that are working from the value of general focus properties such as IsFocused or IsFocusWithin.
Give this a shot it works for a TextBox haven't checked your other Controls
<Application.Resources>
<Style TargetType="TextBox" >
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Control.BorderBrush" Value="Red" />
<Setter Property="Control.BorderThickness" Value="3" />
</Trigger>
</Style.Triggers>
</Style>
</Application.Resources>

Categories