ToolTip style Template Text not working - wpf

I'm trying to change the text color of ToolTips through a style template. But changing the ToolTip Foreground property doesn't change the color no matter what I do. I'm almost certain this is because I also have a TextBlock style that's overriding it.
When attempting to retemplate with a new textblock, it has no effect at all. I've spent all day yesterday fiddling with this issue and searching through threads and have found nothing.. Any contribution would be appreciated.
This is the style in my resource dictionary:
<!-- TextBlock -->
<Style TargetType="{x:Type TextBlock}">
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="#B2FFFFFF"/> <!-- ToolTip text color overridden by this -->
</Style>
<!-- ToolTip -->
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="HasDropShadow" Value="True" />
<Setter Property="Foreground" Value="DarkBlue"/> <!-- has no effect -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToolTip">
<Grid>
<Border Name="Border"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
MinWidth="100"
MinHeight="30"
Margin="0,0,0,50"
Background="Beige"
BorderBrush="Black"
BorderThickness="1"
CornerRadius="10"/>
<TextBlock Foreground="DarkBlue"/> <!-- has not effect -->
<ContentPresenter Margin="4"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

I figured out one solution to this issue.
Removing the TargetType from this line:
<ControlTemplate TargetType="ToolTip">
to read as so:
<ControlTemplate >
and further down in the ControlTemplate, the textblock should be set like this:
<TextBlock
Text="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"
Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource TemplatedParent}}">
</TextBlock>
This allows the text color of a tooltip to be set with the ToolTip's "Foreground" property and is not overridden by other TextBlock styles.

Related

IsMouseOver Property on Button not working

I have this button and wanted to change the design if I hover over it with the mouse. It's not working and I'm not getting an error.
What am I doing wrong?
(I'm really new to WPF)
<Button MaxWidth="180"
Margin="5"
DockPanel.Dock="Top"
Padding="5"
FontSize="12"
Foreground="#1261AC"
FontWeight="SemiBold"
BorderBrush="Transparent">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="LightGray" BorderThickness="1" Padding="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="#157ec4"/>
<Setter Property="Background" Value="#000000"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
The button itself is working but it is not chaning the color of the background or font.
(The colors in my example are just for testing)
The problem with your code is that you define the border-background to be gray.
Now you change the control background using a trigger.
However, the background that is set by the trigger is not yet related to the border background in your example.
I added a template binding that fixes this issue to you. Now the border in your template will always have the Background defined in your style, set by triggers or directly set in XAML.
PLEASE NOTE:
If you set the color in XAML by using <Button Background="Pink"/> this will overwrite the style and trigger attributes.
if you still want to overwrite the background property for a single button for some reason without overwritting the triggers you'll have to create a style based on the original style using the BasedOn Property:
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Propert="Background" Value="Yellow"/>
</Style>
try this piece of art:
ButtonStyle:
<Button Content="Hello there!"
MaxWidth="180"
Margin="5"
DockPanel.Dock="Top"
Padding="5"
FontSize="12"
Foreground="#1261AC"
FontWeight="SemiBold"
BorderBrush="Transparent">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Background" Value="HotPink"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="5" Background="{TemplateBinding Background}" BorderThickness="1" Padding="5">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Background" Value="Lime" />
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>

WPF: How to use BasedOn Style

I am new to WPF and I created the following simple style example. But it doesn't work properly and button's content doesn't show although I can still click on it. Can anyone tell me why it is broken?
<Window.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="Blue"
BorderThickness="5"
Background="Aqua"
Width="80"
Height="40">
<ContentPresenter></ContentPresenter>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="Grid" x:Name="GridWithMarginStyle">
<Setter Property="Margin" Value="12"></Setter>
</Style>
</Window.Resources>
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<EventSetter Event="Button.Click" Handler="ButtonHandler" />
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="Foreground" Value="White"></Setter>
</Style>
</StackPanel.Resources>
<Button Name="OkBtn">OK</Button>
<Button Name="CancelBtn" Click="CancelBtn_Click">Cancel</Button>
</StackPanel>
You are using the BasedOn property in the correct way. The problem is that your ContentPresenter is not binded to the control it renders (i.e. the button).
Just try to replace your ControlTemplate XAML with this one:
<ControlTemplate TargetType="{x:Type Button}">
<Border BorderBrush="Blue"
BorderThickness="5"
Background="Aqua"
Width="80"
Height="40">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</ControlTemplate>
By using TemplateBinding you can bind the ContentPresenter to the Content property of your templated control.

WPF Flat Repeat Button (ToolBar look)

I'm trying to give the RepeatButton the flat look w/o overriding the ControlTemplate. With the regular Button you can do the following (but not with the RepeatButton):
<Button BorderThickness="0" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">...
Is there something similar for the RepeatButton or for ButtonBase? I'm assuming no because if you put a RepeatButton in a ToolBar is does not get a flat look.
Is there a better way to give the RepeatButton a flat look other than overriding the ControlTemplate?
Here's what came up with for a flat RepeatButton Style with a Path as content:
<Style x:Key="RepeatButtonFlat" TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="Transparent" Height="14" Width="14">
<Path HorizontalAlignment="Center" VerticalAlignment="Center" Stretch="Uniform" Margin="2"
Data="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Sample usage:
<RepeatButton Style="{StaticResource ScrollBarLineButton}" Content="M0,0 L1,0 .5,-.5 Z"/>

How to Clear Triggered Control Template

I am trying to achieve the "hint text" functionality for a TextBox in WPF. I can set the default text fine, but the problem comes when I want the control to return its appearance to a normal TextBox. Here is the trigger I have so far:
Trigger A
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBox>
<TextBox.Background>
<VisualBrush AlignmentX="Left" AlignmentY="Center" Stretch="UniformToFill">
<VisualBrush.Visual>
<Label Content="{TemplateBinding TextBox.Tag}" Background="White"/>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
This sets the Background to a VisualBrush when the Text property is empty. What I need to do is clear this ControlTemplate when the user selects the TextBox to input text.
Here is what I tried:
Trigger B
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBox/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
These two don't work together. I tested each by changing the Background colors. If I comment out either one, they will each work. If both are uncommented, Trigger A works and B is never seen. How can I remove/overwrite Trigger A?
I know that the functionality of these templates is supposed to clear when the trigger condition is no longer met, but for example, Trigger A's setting will not go away when I enter text into the TextBox like it should. Like the Text property is still String.Empty or something.
So what am I missing?
EDIT:
Here is the whole style (there's not much more to it):
<UserControl.Resources>
<Style TargetType="TextBox" x:Key="FormsTextBox">
<Setter Property="Width" Value="45"/>
<Setter Property="Margin" Value="3 2 3 2"/>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<TextBox>
<TextBox.Background>
<VisualBrush AlignmentX="Left" AlignmentY="Center" Stretch="UniformToFill">
<VisualBrush.Visual>
<Label Content="{TemplateBinding TextBox.Tag}" Background="White" Width="45"/>
</VisualBrush.Visual>
</VisualBrush>
</TextBox.Background>
</TextBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
I cannot see whole template but this looks a bit overcomplicated. I assume you're trying to achieve watermark text. For hint use box standard ToolTip property, which by default will display your text in a popup when hover your TextBox but this behaviour can be disabled and ToolTip property reused. You can either create reusable Style - which I prefer - for TextBox, something like this:
<Window ...>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
<Style TargetType="{x:Type TextBox}" x:Key="WatermarkTextBoxStyle">
<Setter Property="ToolTipService.IsEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"
BorderThickness="1"
BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}">
<Grid>
<TextBlock Margin="5,0,0,0"
Text="{TemplateBinding ToolTip}"
Visibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}"
Opacity="0.5"/>
<ScrollViewer Name="PART_ContentHost"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<TextBox ToolTip="watermark text" Style="{StaticResource WatermarkTextBoxStyle}"/>
</Window>
or, if it's a one-off thing, then do you can do something like this without any Style or Template:
<Grid Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
<TextBlock Margin="5,0,0,0"
Text="watermark text"
Opacity="0.5"
Visibility="{Binding ElementName=myTextBox, Path=Text.IsEmpty, Converter={StaticResource BooleanToVisibilityConverter}}" />
<TextBox Name="myTextBox" Background="Transparent" />
</Grid>

Label and Expander control with rounded corners

Hi I try make a style with rounded corners for label and expander control.
Label style:
<Style x:Key="InfoLabelStyle" TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Border Name="Border" Background="#BFE3FE" BorderBrush="#BFE3FE" BorderThickness="1" CornerRadius="7" Padding="3">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="12"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="Height" Value="25"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="#BFE3FE"/>
<Setter Property="Background" Value="#BFE3FE"/>
<Setter Property="Margin" Value="2,4,0,1" />
<Setter Property="Padding" Value="4,0,0,0" />
</Style>
I use multibinding on this style in view:
<Label Style="{StaticResource InfoLabelStyle}">
<Label.Content>
<MultiBinding StringFormat="{}{0}, {1} rokov">
<Binding Path="Oponent.Info.Sex" Converter="{StaticResource sexConverter}"/>
<Binding Path= "Oponent.Info.Age"/>
</MultiBinding>
</Label.Content>
</Label>
But if I run app, content of this label is empty, binding is good, I try it on textBox control and work.
Second problem is, I would like have also rounded corners on expander control.
I try same way as in label style:
<Style x:Key="InfoExpanderStyle" TargetType="{x:Type Expander}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Expander}">
<Border Name="Border" Background="#BFE3FE" BorderBrush="#BFE3FE" BorderThickness="1" CornerRadius="7" Padding="3">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Applu style on Expander control:
<Expander Name="InfoExapnder"
Header="{Binding Path=Oponent.Info.Nick, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource InfoExpanderStyle}"
IsExpanded="True"
FontSize="18"
FontWeight="Normal"
Background="#ECEBEB"
Margin="3,0,3,0"
Grid.Row="0">
<Grid>
</Grid>
But result is same, empty content of the control.
What I do bad?
The label is empty because you've re-templated it but not specified where the content should be placed. You want something like:
<ControlTemplate TargetType="{x:Type Label}">
<Border Name="Border" Background="#BFE3FE" BorderBrush="#BFE3FE" BorderThickness="1" CornerRadius="7" Padding="3">
<ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Border>
</ControlTemplate>

Resources