WPF change tab header color - wpf

I am trying to set the tab color of the header when the tab is selected. I work with Mah:
<Style x:Key="MenuLevel2" BasedOn="{StaticResource MetroTabItem}" TargetType="{x:Type TabItem}">
<Setter Property="mah:ControlsHelper.HeaderFontSize" Value="20" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="SteelBlue"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<!-- Sould do the work -->
<Setter Property="Foreground" Value="SteelBlue"/>
</Trigger>
</Style.Triggers>
</Style>
The text of the header is unfortunately still the one from the theme color. Any clue?

Your problem lies in the Controls.TabControl.xaml of MahApps.Metro. Most of the design lies in a template. As you can see in line 227 and 274, the Foreground is not bound to any property like done with other properties like Underline or HeaderFontSize.
This means you can't style these properties explicit without creating a whole new template. Since dynamic resources are used as color a solution is to override the used resources. Here is a workaround to change the colors for a tab item like required:
<TabItem Header="TabItem1">
<TabItem.Resources>
<SolidColorBrush x:Key="AccentColorBrush" Color="SteelBlue"/>
<SolidColorBrush x:Key="HighlightBrush" Color="SteelBlue"/>
</TabItem.Resources>
</TabItem>

Related

XAML Style Trigger - Change Style ONLY for Object of with a specific Name

I am new XAML however I am given the task to override some styles for certain elements within an existing application.
In my custom Theme, I am attempting to override the style of a BORDER control.
From what I can tell (using Snoop) to inspect the application, the element I want to change is just a plain border.
The border also seems to have a Name of "SubMenuBorder". Please see the image below.
Here is the latest iteration of my style snippet in which I am trying to set the border control's Background, BorderBrush and BorderThickness BUT ONLY if the control has a name of "SubMenuBorder"
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<Trigger Property="Name" Value="SubMenuBorder">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="20"></Setter>
</Trigger>
</Style.Triggers>
</Style>
Unfortunately the above does NOT work.
The style trigger does not seem to fire/apply to the intended control.
If I simplify things further and just style ALL borders with the following snippet, then it seems to work and the border control I want to change, is styled, but so is every other border control in the application.
<Style TargetType="{x:Type Border}">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="20"></Setter>
</Style>
Further Findings
I attempted to use a DataTrigger... which unfortunately doesn't work either.
Snoop shows below that the data trigger is being satisfied, however on the second image below you can see that the property of the background and borderbrush are still from the parenttemplate.
Any ideas please?
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Name}" Value="SubMenuBorder">
<Setter Property="Background" Value="Red"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="20"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
You cannot use triggers to modify a Border that is defined in a ControlTemplate, with the exception of using an implicit Style that applies to all elements of the type specified by the TargetType property of the implicit Style.
You will either have to modify the ControlTemplate itself, or programmatically find the Border element in the visual tree and then change its runtime property values. The first approach, i.e. modifying or creating a custom template, is the recommended approach.
The name "SubMenuBorder" is only known and applicable within that Border element's namescope.

WPF override declared style in vb.net

I've declared the below style. How can I override the style foreground color dynamically in my vb.net?
<Style x:Key="LabelWinner" TargetType="{x:Type Label}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="#FF000000" ShadowDepth="6" />
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="#FFFF0000"/>
</Style>
As mentioned in the comment #nit, In WPF have a powerful system behavior properties in the form of Style.Triggers.
Earlier, in WinForms to change a specific property, we had to do it through the code that was not quite comfortable and practical. The developers of WPF decided to separate the visual logic related to the appearance of the program, and business logic, which contains the desired behavior of the program. Actually, it was a Style.
To set the Style trigger, you need to select the appropriate properties. The trigger is as follows:
<Trigger Property="SomeProperty" Value="SomeValue">
... Some actions by way of setters...
</Trigger>
For example, we want to see, when you hover the mouse cursor changes Foreground color and FontSize. Then we choose the property IsMouseOver, and then write a Trigger:
<Style x:Key="LabelWinner" TargetType="{x:Type Label}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect Color="#FF000000" ShadowDepth="6" />
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Green" />
<Setter Property="FontSize" Value="14" />
</Trigger>
</Style.Triggers>
</Style>
It should be remembered, that in WPF have a list of value precedence (MSDN), that the local value of a higher priority than the trigger style. Therefore, if you value for property of Label will be set locally, the trigger will not be able to change it, for example:
<Label Foreground="Red" ... /> <!-- Trigger don't change foreground -->
If the standard property are missing, or the need to implement your scenario, then it have the attached dependency property (MSDN). Inside it, you can set any condition, for example to start the animation and the trigger in the style it will work.
Example of trigger with attached dependency property:
<Trigger Property="local:YourClass.MyProperty" Value="True">
<Setter TargetName="SaveButton" Property="Background" Value="AliceBlue" />
</Trigger>

Use trigger to change colour of a path declared in ResourceDictionary

I'm creating a radiobutton style. The RadioButton has a Border which hosts a ContentControl. The ContentControl has its Content property set to a Path (FemaleVector) declared in a separate ResourceDictionary. How can I change the Fill property of the path when the radiobutton IsChecked? Below is what I have so far. I am able to change the background property of the border but setting the Foreground property of the ContentControl does not change the colour of the path. (Didn't think that would work.)
<Style x:Key="Female" TargetType="{x:Type RadioButton}">
<Setter Property="Margin" Value="0,0,5,0"/>
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border x:Name="border" Padding="7,3,7,3" Width="35" Height="35" BorderBrush="#8CD567DC" Background="#00D567DC" CornerRadius="5" BorderThickness="0.8">
<ContentControl x:Name="content" Content="{DynamicResource FemaleVector}"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" TargetName="border" Value="#8CD567DC"/>
<Setter Property="Foreground" TargetName="content" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I don't like having the long Data property of paths in my Styles, so I have moved them into a separate ResourceDictionary. Should I just put the Path back into my Style instead of keeping it in a separate ResourceDictionary?
Edit: similar questions are here and here.
If the style is not reused somewhere, I would personally keep it in local style resources section. That way you see bigger picture. Otherwise it would be wise to keep it in ResourceDictionary :)
Either way you should be able to change Fill property with:
<Setter Property="Content.Fill" TargetName="content" Value="Blue"/>
If this is not working, I advise few ways more:
You can use Trigger.EnterActions<> in Xaml. Perhaps setting property through animation will have better effect? ControlTemplate triggers with setters are sometimes way limiting.
There's also relative binding. But you gotta be careful with that. (If you pla to make it reusable)
In your FemaleVector style, you can bind Fill against ContentControl Foreground. Look for RelativeBinding in Google.
And then there's property inheritance. If you set Fill color in FemaleVector, you need to do it with style. Such as:
<Style>
<Setter Property="Fill" Value="BLACK" />
</Style>
you can later set ContentControls Style and add trigger there, like:
<ContentControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding={Binding IsChecked, RelativeSource={RelativeSource AncestorType=RadioButto}} Value=TRUE>
<Setter Property="Path.Fill" Value="BLACK" />
</DataTrigger>

Unable to set Background property of MenuItem for IsPressed event

I want to change the background of a MenuItem when the MenuItem is pressed.
<Style x:Key="{x:Type MenuItem}" TargetType="MenuItem">
<Style.Triggers>
<Trigger Property="MenuItem.IsPressed" Value="True">
<Setter Property="MenuItem.Background" Value="#FFE389" />
<Setter Property="MenuItem.BorderBrush" Value="#C2762B" />
</Trigger>
</Style.Triggers>
</Style>
I tried doing the above, but the trigger does not seem to work. Is the Trigger wrong?
Update: It works for the event IsMouseOver but IsPressed does not seem to work
Update 2: It works for TopLevelMenuItems but does not work for TopLevelMenuHeaderItems.
Try this...which does not preface the property names with MenuItem and modify your TargetType and x:Key syntax...
<Style x:Key="MyStyle" TargetType="{x:Type MenuItem}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#FFE389" />
<Setter Property="BorderBrush" Value="#C2762B" />
</Trigger>
</Style.Triggers>
</Style>
EDIT:
Based on your updates take a look at how a default MenuItem is constructed via XAML. This should get you where you need to go in providing styling for the varying parts of the MenuItem. Note the use of the Role property within the MenuItem style dealing with the headers and items at both the top level and sub level.

Changing Hyperlink foreground without losing hover color

I'm writing a WPF app, and I want some of my hyperlinks to be the default blue, and others to be green. No problem -- I can just set Foreground:
<TextBlock><Hyperlink Foreground="#0C0">Mark as done</Hyperlink></TextBlock>
The trouble is, when I do this, the hover effect goes away. In a normal Hyperlink, when I move the mouse over the link, it turns red, and when I move the mouse away, it goes back to blue. But in a Hyperlink with the Foreground property assigned, it's always that color -- the red-on-hover is totally suppressed.
How can I change a Hyperlink's color, without losing the default hover behavior and color?
Setting the Foreground directly (as you've done) doesn't work, and setting it in a Style doesn't work either, unless you "derive" that style from the default Hyperlink style (which must include the OnMouseOver trigger). So this works:
<TextBlock>
<Hyperlink>
<Hyperlink.Style>
<Style TargetType="Hyperlink"
BasedOn="{StaticResource {x:Type Hyperlink}}">
<Setter Property="Foreground" Value="#0C0"/>
</Style>
</Hyperlink.Style>
Mark as done
</Hyperlink>
</TextBlock>
Extracting that style back into the Window resources and referencing it with a key would probably make for more-readable XAML, but the above code does the job.
You should build your Hyperlink like this
<TextBlock Width="Auto" HorizontalAlignment="Center">
<Hyperlink Click="ForgotPassword_Clicked">
<TextBlock Text="Forgot Password?"/>
</Hyperlink>
</TextBlock>
And then this style should work for you
<Style TargetType="{x:Type Hyperlink}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="Blue" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextBlock.TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>

Resources