Can we customize WPF MenuItem style on IsPressed - wpf

MainWindow.xaml:
<mah:MetroWindow x:Class="Wpf_MahAppsTEST.MainWindow"
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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
xmlns:local="clr-namespace:Wpf_MahAppsTEST"
mc:Ignorable="d"
Title="MainWindow" Height="850" Width="800">
<mah:MetroWindow.Resources>
<SolidColorBrush x:Key="MahApps.Brushes.MenuItem.SelectionFill" Color="{StaticResource MahApps.Colors.Accent3}" />
<Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="MenuItem" x:Key="MenuStyle">
<Setter Property="Background" Value="{StaticResource MahApps.Brushes.Accent}"/>
<Setter Property="Foreground" Value="{StaticResource MahApps.Brushes.IdealForeground}"/>
</Style>
</mah:MetroWindow.Resources>
<Grid>
<Menu>
<MenuItem Header="_File">
<MenuItem.Resources>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MenuStyle}"/>
</MenuItem.Resources>
<MenuItem Header="_New" />
<MenuItem Header="_Open" />
<MenuItem Header="_Save" />
</MenuItem>
</Menu>
</Grid>
</mah:MetroWindow>
Display of above window:
As shown below, when we press (Ref: MenuITem.IsPressed) the File item of the menu, the background of the File item is showing as default (gray). Question How can we make the background of the File item look the same as the background of its child items when you mouse over a child item (such as the background of Open item as depicted below)?
For example, (without MahApps), the default look as follows - where background of both the File item and the Open item match. I am looking for a similar scenario in the above example for MahApp:

Just add another brush resource:
<mah:MetroWindow.Resources>
<SolidColorBrush x:Key="MahApps.Brushes.TopMenuItem.PressedFill"
Color="{StaticResource MahApps.Colors.Accent3}" />
<SolidColorBrush x:Key="MahApps.Brushes.MenuItem.SelectionFill" Color="{StaticResource MahApps.Colors.Accent3}" />
<Style BasedOn="{StaticResource MahApps.Styles.MenuItem}" TargetType="MenuItem" x:Key="MenuStyle">
<Setter Property="Background" Value="{StaticResource MahApps.Brushes.Accent}"/>
<Setter Property="Foreground" Value="{StaticResource MahApps.Brushes.IdealForeground}"/>
</Style>
</mah:MetroWindow.Resources>

Related

how to create a resource based on resource dictionary in WPF

I create a resource dictionary that receives 2 parmeters : releasedImage and PressedImage :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SwitchesLibrary">
<Style TargetType="local:ImageButton" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ImageButton">
<Grid>
<Image x:Name="PressedButton"
Source="{TemplateBinding PressedImage}" />
<Image x:Name="ReleasedButton"
Source="{TemplateBinding ReleasedImage}" />
</Grid>
</Setter.Value>
</Setter>
</Style>
In another lib, I will use several buttons with the same images. So I want to create a resource in this lib with specific PressedImage and ReleasedImage,
like this :
<UserControl x:Class="ExamplePanelLibrary.ExamplePanelControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ExamplePanelLibrary"
xmlns:SwitchesLibrary="clr-namespace:SwitchesLibrary;assembly=SwitchesLibrary"
mc:Ignorable="d"
d:DesignHeight="760" d:DesignWidth="754">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary
Source="pack://application:,,,/SwitchesLibrary;component/ImageButtonStyle.xaml">
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
<ImageBrush x:Key="ButtonPressed" ImageSource="Images/PushButtons/OSB_Pushed.png"/>
<ImageBrush x:Key="ButtonReleased" ImageSource="Images/PushButtons/OSB_Released.png"/>
<Style
x:Key="OSBPushButton"
TargetType="SwitchesLibrary:ImageButton"
ReleasedImage="Images/SpecificButtonReleased.png"
PressedImage="Images/SpecificButtonPressed.png"
/>
</ResourceDictionary>
Can we do something like that ?
This may work:
<Style x:Key="OSBPushButton"
TargetType="SwitchesLibrary:SpecificImageButton"
BasedOn="{StaticResource {x:Type local:ImageButton}}">
<Setter Property="ReleasedImage" Value="Images/SpecificButtonReleased.png"/>
<Setter Property="PressedImage" Value="Images/SpecificButtonPressed.png"/>
</Style>
Clemens gave the correct answer. I just want to rewrite this clearly :
<Style
x:Key="OSBPushButton"
TargetType="SwitchesLibrary:ImageButton"
BasedOn="{StaticResource {x:Type SwitchesLibrary:ImageButton}}">
<Setter Property="ReleasedImage" Value="Images/SpecificButtonReleased.png"/>
<Setter Property="PressedImage" Value="Images/SpecificButtonPressed.png"/>
</Style>
and use it like this :
<SwitchesLibrary:ImageButton x:Name="OSB_1" Style="{StaticResource OSBPushButton}"/>

Overriding application wide style

I want to define a global style for textblock in the application but I also want to be able to override this default style. I always thought that the local override of style has more priority than the global one but it doesn't seems to be the case?
In the following example, the Button with content "Test" will have a "Red" foreground when I expect it to be "Aqua". If I remove the global style in Application.Resources, than it will works. Did I'm missing something?
App.xaml
<Application x:Class="ContextMenuTest.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red" />
</Style>
</Application.Resources>
MainWindow.xaml
<Window x:Class="ContextMenuTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type MenuItem}" x:Key="DefaultMenuItemStyle">
<Setter Property="Foreground" Value="DarkGreen" />
</Style>
<Style TargetType="{x:Type Button}" x:Key="DefaultButtonStyle">
<Setter Property="Foreground" Value="DarkGreen" />
</Style>
</Window.Resources>
<Grid Background="Black">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Menu 1" Style="{StaticResource DefaultMenuItemStyle}" />
<MenuItem Header="Menu 2" Style="{StaticResource DefaultMenuItemStyle}" />
<MenuItem Header="Menu 3" Style="{StaticResource DefaultMenuItemStyle}" />
<MenuItem Header="Menu 4" Style="{StaticResource DefaultMenuItemStyle}" />
<MenuItem Header="Menu 5" Style="{StaticResource DefaultMenuItemStyle}" />
</ContextMenu>
</Grid.ContextMenu>
<Button Content="Test" Style="{StaticResource DefaultButtonStyle}" Foreground="Aqua" />
</Grid>
Implicit TextBlock defined in App.xaml will not be overrided by other TextBlock styles. It's therefore recommended that you move your default TextBlock style to for example <Window.Resources>.
Please refer to the following links for more information about this.
Implicit styles in Application.Resources vs Window.Resources?
Over ride the Property setting in App.xaml: https://social.msdn.microsoft.com/Forums/vstudio/en-US/f6822a5e-09c7-489b-b85d-833f1f9356dc/over-ride-the-property-setting-in-appxaml?forum=wpf
Or simply don't define any implicit TextBlock style. Define a default Style for each Control instead.
Your problem is in defining your application level resources for the TextBlock instead of the Button. Most of WPF controls use TextBlocks as default way to display text content, so by trying to override your Button Foreground, you are doing it, but then it gets overriden again by TextBlock default style.
Change your App.xaml to this and you will get the result you wanted to achieve:
<Application.Resources>
<Style TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Red" />
</Style>
</Application.Resources>

Extend style without setting an x:Key attribute in the base style

I have a file MyButtonStyles.xaml which designs the WPF button. This file uses a style to set some colors and fonts:
<ResourceDictionary xmlns......>
<Style BasedOn="{StaticResource {x:Type Button}} TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="Blue" />
<Setter Property="FontSize" Value="22" />
</Style>
</ResourceDictionary>
This button is used in two xaml files. One shows the button as designed in the above style. This happens automatically because the above style has the according TargetType and it does not have an x:Key attribute.
In the other xaml file I use this button as well but the style from above should be extended by another setter property. Doing this by merging the dictionaries and basing on the original style it works:
<ResourceDictionary>
<ResourceDictionary.MergedDictionary>
<ResourceDictionary Source="MyButtonStyles.xaml" />
<ResourceDictionary.MergedDictionary>
<Style BasedOn="ButtonStylesOrig" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
</Style>
</ResourceDictionary>
But for this I have to add an x:Key attribute (ButtonStylesOrig) to the base style. This means that in the first xaml which uses the button the base style will not be applied any more.
Is there a possibility to extend a style without losing the global scope of it (e.g. without using x:Key)?
This works:
<Window x:Class="WpfApplication1.Window1"
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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="MyButtonStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Button}" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Background" Value="Green" />
</Style>
</Grid.Resources>
<Button Content="Button" />
</Grid>
</Window>
The key is not to override the resource in the same resource dictionary that you merge your base style into:
WPF Using multiple Resource Dictionaries from multiple projects
You can't combine multiple default styles of the same type a single resource scope. However, it is possible to build default styles in nested resource scopes.
Suppose you merge MyButtonStyles.xaml into the App.xaml resources. Then you can place your second style with the additional setter into Window.Resources or other deeper nested resources and it will combine the correct implicit styles.
A more localized example:
<Grid>
<Grid.Resources>
<ResourceDictionary Source="MyButtonStyles.xaml"/>
</Grid.Resources>
<Grid>
<Grid.Resources>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="{x:Type Button}">
<Setter Property="Background" Value="Green" />
</Style>
</Grid.Resources>
<Button VerticalAlignment="Top" Margin="20">Both styles</Button>
</Grid>
<Button VerticalAlignment="Center" Margin="20">ExampleDictionary style</Button>
</Grid>

How to apply DependencyProperty values to child user controls?

I have multiple instances of the same custom user control in a StackPanel. Each instance needs the same DependencyProperty "ControlWidth". Instead of setting each user control with the same property, I want to set it only once in the parent StackPanel
<StackPanel>
<propwin:PropertyEditControl Label="First" ControlWidth="180" />
<propwin:PropertyEditControl Label="First" ControlWidth="180" />
...
</StackPanel>
I used to do this with Style properties
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type propwin:PropertyEditControl}">
<Setter Property="ControlWidth" Value="180" />
</Style>
</StackPanel.Resources>
<propwin:PropertyEditControl Label="First" />
<propwin:PropertyEditControl Label="Second" />
...
</StackPanel>
Update:
Thanks to Anatoliy, who mention that my code (the one I showed here) should work. I now tracked down the problem. Inside my PropertyEditControl.xaml I define a validation style:
<UserControl x:Class="MyModule.PropertyEditControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:MyModule">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MyModule;component/UI/ResourceDictionaries/ResourceLibrary.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="local:PropertyEditControl">
<Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationErrorTemplate}" />
</Style>
<Style x:Key="PropertyNameStyle" TargetType="DockPanel">
<Setter Property="Width" Value="{Binding ControlWidth}" />
<Setter Property="DockPanel.Dock" Value="Left" />
</Style>
...
If I remove the <Style TargetType="local:PropertyEditControl"> style it works!
It turned out that my original approach should have worked. The reason why it hasn't was a misplaced Style Resource inside the user control. Anyway, the correct answer to my initial question is: To set a DependencyProperty value for multiple controls only once, you have to set it inside the container style definition:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type propwin:PropertyEditControl}">
<Setter Property="ControlWidth" Value="180" />
</Style>
</StackPanel.Resources>
<propwin:PropertyEditControl Label="First" />
<propwin:PropertyEditControl Label="Second" />
...
</StackPanel>

ComponentOne DataGridColumnHeaderPresenter Style Inheritance does not work (Silverlight)

I'm using ComponentOne C1DataGrid control for Silverlight. Standard StyleInheritance does not work.
Here is the code:
<UserControl x:Class="TestSLStyles.MainPage"
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"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
xmlns:sys="clr-namespace:System.Collections.ObjectModel;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<Style x:Key="BaseStyle" TargetType="Button">
<Setter Property="Background" Value="Yellow" />
</Style>
<Style x:Key="InheritedStyle" TargetType="Button" BasedOn="{StaticResource BaseStyle}">
<Setter Property="Foreground" Value="Red" />
</Style>
<Style x:Key="dchpBase" x:Name="dchpBase" TargetType="c1:DataGridColumnHeaderPresenter">
<Setter Property="Background" Value="Yellow"/>
</Style>
<Style x:Key="dchpInherited" x:Name="dchpInherited" TargetType="c1:DataGridColumnHeaderPresenter" BasedOn="{StaticResource dchpBase}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</UserControl.Resources>
<StackPanel>
<Button Content="HelloWorld" x:Name="btn1" />
<Button Content="HelloWorld" x:Name="btn2" Style="{StaticResource BaseStyle}" />
<Button Content="HelloWorld" x:Name="btn3" Style="{StaticResource InheritedStyle}" />
<c1:C1DataGrid x:Name="grd1">
<c1:C1DataGrid.Columns>
<c1:DataGridTextColumn Header="Column1" x:Name="cln1" />
<c1:DataGridTextColumn Header="Column2" x:Name="cln2" HeaderStyle="{StaticResource dchpBase}" />
<c1:DataGridTextColumn Header="Column3" x:Name="cln3" HeaderStyle="{StaticResource dchpInherited}" />
</c1:C1DataGrid.Columns>
</c1:C1DataGrid>
</StackPanel>
</UserControl>
As you can see on screen below, this code works fine for Button's style inheritance, but not for grid's column header:
The last column supposed to be with Yellow background and Red foreground, but base style is not inherited. Tested on Silverlight 5 and ComponentOne version 4.0.20103.86
Question was posted to ComponentOne's forum as well
The issue was fixed with the C1Silverlight Build : 5.0.20133.381
The latest build can be downloaded from the following link :http://prerelease.componentone.com/hotfixes/silverlight/C1Silverlight_5.0.20141.399_RC1.msi

Resources