I have a WPF label and want to change its look on mouse over or hover.
This question shows how to do it with TextBlock and not quite what I want using a trigger to set a textblock foreground on mouseover.
It's different because with Label, changing foreground did not work.
Using the example from the question that you linked from, but changing the word TextBlock to Label works just fine for changing the Foreground, so you'll have to provide more information if you really can't get it to work. Try this:
<Label Content="My colour changes just fine" HorizontalContentAlignment="Center"
VerticalContentAlignment="Center">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Note that if you set the Foreground on the actual Label element, as you did in your answer, instead of in the Style then that would stop the Trigger from working, so don't do this:
<Label Content="My colour changes just fine" HorizontalContentAlignment="Center"
VerticalContentAlignment="Center" Foreground="Black">
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Blue" /> <!-- This won't work -->
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" /> <!--This won't work-->
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Here is how you can do it. Ignore other properties, focus on Label.Style.
Using a Label allows you to align text as I showed below. That does not work with TextBlock.
<Label Content="Hover over me" Name="lblSeasons" FontWeight="Bold" Foreground="DarkBlue" Width="150" HorizontalContentAlignment="Center" Height="50"
VerticalContentAlignment="Center" >
<Label.Style>
<Style TargetType="Label">
<Setter Property="Foreground" Value="Green"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Green"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="BorderBrush" Value="Aqua"/>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
Related
I have created a Button with an image that you can see below:
I used the following XAML code to create this Button:
<Button Grid.Column="3" Style="{StaticResource MaterialDesignFlatButton}" Padding="0"
ToolTip="Settings" Width="30"
IsEnabled="{Binding DataContext.ControlsEnabled, RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}">
<materialDesign:PackIcon Kind="Cog" Width="32" Height="32" VerticalAlignment="Center" HorizontalAlignment="Center">
<materialDesign:PackIcon.Style>
<Style TargetType="materialDesign:PackIcon">
<Setter Property="Foreground" Value="WhiteSmoke" />
<Setter Property="Opacity" Value="0.7" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</materialDesign:PackIcon.Style>
</materialDesign:PackIcon>
</Button>
My problem is that the icon color is changed only when the mouse is over the icon, not the Button. I want it to change color when the mouse is over the Button.
How can I fix it in my code?
You can use a RelativeSource binding to refer to the IsMouseOver property of the parent Button.
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type Button}}}" Value="True">
<Setter Property="Foreground" Value="White" />
<Setter Property="Opacity" Value="1" />
</DataTrigger>
</Style.Triggers>
Short background on the problem: I am trying to make a readable, xaml only TextBox Placeholder, which is packed to a ResourceDictionary.
At this point - I have made a well working prototype, which looks and used on the page like this:
<Grid>
<TextBox Style="{StaticResource SearchBox}"
Width="325"
x:Name="UsarioDisponiblesSearch"/>
<TextBlock IsHitTestVisible="False"
Text="Search..."
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="5,0,0,0"
Foreground="{StaticResource WhiteFadedBrush}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=UsarioDisponiblesSearch}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Image Source="/img/search.png" Height="15" HorizontalAlignment="Right" Margin="0,0,5,0" />
</Grid>
Grid, that holds the SearchBox consist of 3 elements:
TextBox - which will receive search string;
TextBlock - which actually holds the PlaceHolder. It disapears, as soon as ElementName of TextBox is not an empty string;
Image - custom icon on the right from the SearchBox.
What I want to achieve is a look like this on the page:
<Grid>
<TextBox Style="{StaticResource SearchBox}"
Width="325"
x:Name="UarioDisponiblesSearch"/>
<TextBlock Style="{StaticResource PlaceHolder}"
x:Name="{Binding Text, ElementName=UarioDisponiblesSearch}" />
</Grid>
And like around this styles, described in the ResourceDictionary:
<Style x:Key="SearchBox" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Margin" Value="5,0,0,0" />
<Setter Property="Foreground" Value="{StaticResource WhiteBrush}" />
</Style>
<Style x:Key="Placeholder" TargetType="{x:Type TextBlock}">
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="Text" Value="Search..." />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Margin" Value="5,0,0,0" />
<Setter Property="Foreground" Value="{StaticResource WhiteFadedBrush}" />
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
The main obstacle on my way there is the Binding, because I am not really good still in understanding how does it work, and the fact, that at this point three elements will have to share the same Name property (Which I suppose is a pretty huge obstacle as well).
I am not sticking to exactly this construction but I want it to be reusable, useful for the community and neat looking.
This XAML will give a templated TextBox that will display a given message if the Text is empty on the TextBox and it does not have focus. So when you click it the message disappears, and if you enter text (or have bound text) the message will also disappear.
You can do any further fancy bindings and such if you want to make it more re-usable. I.E. you could templatebind the DisplayText.Text to something to allow for dynamic messages.
When I was doing a quick search as I was styling, I stumbled on This, which is almost the same thing. So it would be worth giving fair reference. I prefer to use keys and compartmentalize my templates and styles. In the event I want a slightly different style elsewhere, then i can just do a BasedOn Style (which i do often). It is really 6 of one and half a dozen of another (although I didn't test the linked code).
<ControlTemplate x:Key="SearchMessageTextBoxControlTemplate" TargetType="{x:Type TextBox}">
<Grid>
<Grid x:Name="SearchTextGrid">
<ScrollViewer x:Name="PART_ContentHost" Background="{TemplateBinding Background}" />
<TextBlock x:Name="DisplayText" Text="Type Your Search..."
HorizontalAlignment="Center"
VerticalAlignment="Center"
Opacity="0.5"
Visibility="Hidden"
FontSize="{TemplateBinding FontSize}"/>
</Grid>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter TargetName="DisplayText" Property="Visibility" Value="Hidden"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsFocused" Value="False"/>
<Condition Property="Text" Value=""/>
</MultiTrigger.Conditions>
<Setter TargetName="DisplayText" Property="Visibility" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="WaterMarkMessageTextBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="20"/>
<Setter Property="Background" Value="DarkSlateGray"/>
<Setter Property="CaretBrush" Value="White"/>
<Setter Property="Foreground" Value="#F2FFE5"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="BorderThickness" Value="2"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Template" Value="{StaticResource SearchMessageTextBoxControlTemplate}"/>
</Style>
You would use it as follows:
<TextBox Style="{StaticResource WaterMarkMessageTextBoxStyle}"/>
I am trying to style my WPF TabControl. I basically want to get the tab control to have a transparent background, with a white border and text. I want the selected tab to have a White Background and Transparent Text (or any colour text!). Essentially a 2 colour tab.
However, I cannot override the selected tab appearance - this shows as white. And my child textboxes are taking the style of the TabItem font. Note, in the screen shot my labels have their own style set so do not take the TabItem font.
I have the following XAML in place to do this. Ideally I want to create the styles so that I can reuse across the application.
Resource Dictionary
<ResourceDictionary 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">
<Style x:Key="Tabs" TargetType="TabControl">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="White"/>
</Style>
<Style x:Key="TabItemStyle" TargetType="TabItem">
<Setter Property="Foreground" Value="White" />
<Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
Then the XAML MarkUp
<TabControl Style="{StaticResource Tabs}">
<TabItem Header="General" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="Details" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="Info" Style="{StaticResource TabItemStyle}">...</TabItem>
<TabItem Header="More Stuff..." Style="{StaticResource TabItemStyle}">...</TabItem>
</TabControl>
How can I style my tabs to be and prevent the children from sizing?
Your DataTriggers don't work. To fix it change RelatveSource to Self
Binding="{Binding Path=IsSelected, RelativeSource={RelativeSource Self}}"
However I would suggest to change them to Triggers like so:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="White"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="LightGray"/>
<Setter Property="Background" Value="Transparent"/>
</Trigger>
</Style.Triggers>
You should create control template for TabItem.
This sample change TabItem background to Transparent and Text color to White.
You can use own color schema.
<Window.Resources>
<Style TargetType="TabControl">
<Setter Property="Background"
Value="Transparent" />
<Setter Property="BorderBrush"
Value="White" />
</Style>
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border Name="Border"
Margin="0,0,-4,0"
Background="{x:Static Brushes.White}"
BorderBrush="{x:Static Brushes.White}"
BorderThickness="1,1,1,1"
CornerRadius="2,12,0,0">
<ContentPresenter x:Name="ContentSite"
Margin="12,2,12,2"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ContentSource="Header"
RecognizesAccessKey="True" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="Panel.ZIndex"
Value="100" />
<Setter TargetName="Border"
Property="Background"
Value="{x:Static Brushes.Transparent}" />
<Setter TargetName="Border"
Property="BorderThickness"
Value="1,1,1,0" />
<Setter Property="TextBlock.Foreground"
Value="White" />
<!--<Setter Property="TextBlock.Foreground"
Value="Transparent" />-->
</Trigger>
<Trigger Property="IsEnabled"
Value="False">
<Setter TargetName="Border"
Property="Background"
Value="{x:Static Brushes.White}" />
<Setter TargetName="Border"
Property="BorderBrush"
Value="{x:Static Brushes.White}" />
<Setter Property="Foreground"
Value="{x:Static Brushes.White}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Background="SkyBlue">
<TabControl Margin="20">
<TabItem Header="TabItem #1">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
<TabItem Header="TabItem #2">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
<TabItem Header="TabItem #3">
<TextBox>Tab Item #1 content</TextBox>
</TabItem>
</TabControl>
</Grid>
My textbox :
<TextBox Grid.Column="1" TextWrapping="Wrap" Height="50">
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Foreground" Value="DarkGray"/>
<Setter Property="Text" Value="Must be seperated with coma"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Text" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
The problem is : when I put my mouse on the textbox, the foreground change in red, that's cool but the text doesn't clear up. Have you any idea of why ?
Thanks a lot !
I am going crazy here! What am I missing and why it is not styling anything:
<Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<TextBox Width="100" Style="{StaticResource textBoxStyle}" Height="20" Background="Yellow" ></TextBox>
The above code does not do anything. It does not highlight the TextBox control!
This occurs because local values override style values. (Properties set directly on an element have very high precedence.) You are setting Background directly on the TextBox, so WPF is going, "Well, he normally wants textBoxStyle backgrounds to be Red when focused, but for this particular TextBox, he's said he specifically wants Background to be Yellow, so Yellow it is."
So the fix is to move the Yellow background to be part of the Style:
<Style x:Key="textBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Background" Value="Yellow" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
and remove it from the TextBox:
<TextBox Width="100" Style="{StaticResource textBoxStyle}" Height="20" />
Define your Style before the TextBox or use DynamicResource instead of StaticResource