Using the code provided in this post:
lighten background color on button click per binding with converter
I have written the following code to change the background of a MahApps Tile on MouseOver:
<local:ColorLightConverter x:Key="colorLightConverter" />
<Style x:Key="aaa" TargetType="mah:Tile">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Path=Background.Color, RelativeSource={RelativeSource TemplatedParent}, Mode=OneTime, Converter={StaticResource colorLightConverter}}" />
</Trigger>
</Style.Triggers>
</Style>
The color light converter is the same as written in the post mentioned and the style is used on the Mahapps Metro Tile. The code does not work, because the tile flickers on MouseOver. Also, placing a breakpoint inside the converter, I saw that it is not reached.
What am I doing wrong?
I could reproduce the problem with the Tile control. It never enters the Converter code because TemplatedParent is null. When I changed the RelativeSource to AncestorType={x:Type StackPanel} as it was in my case, the flickering went away and the breakpoint in the converter was reached. You can check if this is the case with you by adding to the Binding FallbackValue=Red in which case the color on mouse over will be Red for a faulty binding.
Here is my working XAML:
<Window.Resources>
<local:ColorLightConverter x:Key="colorLightConverter" />
<Style x:Key="aaa" TargetType="{x:Type Control}">
<Setter Property="Background" Value="White"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Path=Background.Color, RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Converter={StaticResource colorLightConverter},FallbackValue=Red}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Background="DarkGoldenrod">
<mah:Tile Title="Hello!" Style="{StaticResource aaa}"
TiltFactor="2"
Width="100" Height="100"
Count="1" x:Name="tile">
</mah:Tile>
<TextBox Width="100" Height="100" Style="{StaticResource aaa}">Test</TextBox>
</StackPanel>
OK. So this is the MainWindow.xaml:
<mah:MetroWindow
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:local="clr-namespace:NQR_GUI_WPF"
xmlns:prop="clr-namespace:NQR_GUI_WPF.Properties"
xmlns:Custom="http://metro.mahapps.com/winfx/xaml/controls"
x:Class="NQR_GUI_WPF.MainWindow"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d" Height="600" Width="800" ResizeMode="CanResizeWithGrip" WindowStartupLocation="CenterScreen" TitlebarHeight="28"
GlowBrush="{DynamicResource AccentColorBrush}" ShowIconOnTitleBar="False" Icon="Pictures/icon.ico"
>
<Window.Resources>
<local:ColorLightConverter x:Key="colorLightConverter" />
<Style x:Key="aaa" TargetType="{x:Type Control}">
<Setter Property="Background" Value="White"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding Path=Background.Color, Mode=OneTime, RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}, Converter={StaticResource colorLightConverter}}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel Background="DarkGoldenrod">
<mah:Tile Title="Hello!" Style="{StaticResource aaa}"
TiltFactor="2"
Width="100" Height="100"
Count="1" x:Name="tile">
</mah:Tile>
<TextBox Width="100" Height="100" Style="{StaticResource aaa}">Test</TextBox>
</StackPanel>
This is the App.xaml
<Application x:Class="NQR_GUI_WPF.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NQR_GUI_WPF"
xmlns:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary>
<BitmapImage x:Key="settingsIcon" UriSource="Pictures/settings1_unpressed.png" />
<ResourceDictionary.MergedDictionaries>
<!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
<!-- Accent and AppTheme setting -->
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
This is the color converter code:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Color color = (Color)value;
System.Drawing.Color darkColor = System.Windows.Forms.ControlPaint.Dark(System.Drawing.Color.FromArgb(color.A, color.R, color.G, color.B), 0.1f);
return System.Drawing.Color.FromArgb(darkColor.A, darkColor.R, darkColor.G, darkColor.B);
}
I am using MahApps 1.2.4.0.
Related
I am using MahApps.Metro in my WPF app. The default behavior of the title bar of its MetroWindow is that any icon inside it has low opacity (dimmed) display unless you mouseover the icon. Even if you don't mouseover the icon, I would like to look it the same as when you mouseover it. How can we achieve this?
With mouseover on CupCakes icon [I would like it to look the same even without mouseover]:
Without mouseover:
MetroWindow.xaml:
<mah:MetroWindow x:Class="WPF_Mah_Metro_Test.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:mah="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPF_Mah_Metro_Test"
mc:Ignorable="d"
GlowBrush="{DynamicResource MahApps.Brushes.Accent}"
ResizeMode="CanResizeWithGrip"
WindowStartupLocation="CenterScreen"
Height="450" Width="800">
<mah:MetroWindow.LeftWindowCommands>
<mah:WindowCommands>
<Button x:Name="btnTest" Click="btnTest_Click" ToolTip="Open up the GitHub site">
<iconPacks:PackIconModern Width="22" Height="22" Kind="SocialGithubOctocat" />
</Button>
</mah:WindowCommands>
</mah:MetroWindow.LeftWindowCommands>
<mah:MetroWindow.RightWindowCommands>
<mah:WindowCommands>
<Button x:Name="btnTest1" Click="btnTest1_Click" Content="Deploy CupCakes">
<Button.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<iconPacks:PackIconModern Width="22" Height="22" VerticalAlignment="Center" Kind="FoodCupcake" />
<TextBlock Margin="4 0 0 0" VerticalAlignment="Center" Text="{Binding}" />
</StackPanel>
</DataTemplate>
</Button.ContentTemplate>
</Button>
</mah:WindowCommands>
</mah:MetroWindow.RightWindowCommands>
<Grid>
</Grid>
</mah:MetroWindow>
To override the styles of the inner controls of the WindowCommands you must create your own style for it:
<Style x:Key="Styles.WindowCommands.Custom"
BasedOn="{StaticResource MahApps.Styles.WindowCommands}"
TargetType="{x:Type mah:WindowCommands}">
<Style.Resources>
<ResourceDictionary>
<Style BasedOn="{StaticResource MahApps.Styles.Button.WindowCommands}" TargetType="{x:Type Button}">
<Setter Property="Opacity" Value="1" />
</Style>
<Style BasedOn="{StaticResource MahApps.Styles.ToggleButton.WindowCommands}" TargetType="{x:Type ToggleButton}">
<Setter Property="Opacity" Value="1" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Opacity" Value="1" />
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
<Style BasedOn="{StaticResource MahApps.Styles.SplitButton.WindowCommands}" TargetType="{x:Type mah:SplitButton}">
<Setter Property="Opacity" Value="1" />
</Style>
<Style BasedOn="{StaticResource MahApps.Styles.DropDownButton.WindowCommands}" TargetType="{x:Type mah:DropDownButton}">
<Setter Property="Opacity" Value="1" />
</Style>
</ResourceDictionary>
</Style.Resources>
</Style>
Now if you put this key to your `App.xaml you can use it in your App like:
<mah:MetroWindow.LeftWindowCommands>
<mah:WindowCommands Style="{StaticResource Styles.WindowCommands.Custom}">
</mah:WindowCommands>
</mah:MetroWindow.LeftWindowCommands>
<mah:MetroWindow.RightWindowCommands>
<mah:WindowCommands Style="{StaticResource Styles.WindowCommands.Custom}">
</mah:WindowCommands>
</mah:MetroWindow.RightWindowCommands>
Another solution could be to make a style for the Button directly.
Note: Namespace for mah is xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
I am trying to make window frame appear when user hovers "mybutton". This should work but for some reason it is not. What am I missing?
<Window x:Class="test2.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" WindowStyle="None" Loaded="ShellWindow_SourceInitialized" x:Name="mywindow">
<Window.Resources>
<Style TargetType="{x:Type Window}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="True">
<Setter Property="ResizeMode" Value="CanResize" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="False">
<Setter Property="ResizeMode" Value="NoResize" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid Name="mygrid" Loaded="Grid_Loaded">
<Button Name="mybutton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
</Grid>
(In case you are wondering what those "Loaded" functions are, they remove chrome while keeping the shadow and allowtransparency=false
http://marcin.floryan.pl/blog/2010/08/wpf-drop-shadow-with-windows-dwm-api)
At the end it will not be button but will react on whole window border (I can not find better way to enable resizing while removing all chrome)
In the style TargetType should be MainWindow
<Style TargetType="{x:Type local:MainWindow}">
where local has to be mapped to your namespace:
xmlns:local="clr-namespace:test2"
myButton is defined after style. XAML parser is not that smart. User the following XAML to get your intended behavior:
<Window x:Class="test2.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" WindowStyle="None" Loaded="ShellWindow_SourceInitialized" x:Name="mywindow">
<Grid Name="mygrid" Loaded="Grid_Loaded" >
<Button Name="mybutton" Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75"/>
</Grid>
<Window.Style>
<Style TargetType="{x:Type Window}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="True">
<Setter Property="ResizeMode" Value="CanResize" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=IsMouseOver, ElementName=mybutton}" Value="False">
<Setter Property="ResizeMode" Value="NoResize" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Style>
</Window>
I am trying to create a style for a textblock to create a highlight effect. This style will be used on a number of TextBlocks, each bound to a different property. The datacontext for my main control is set in code behind:
this.DataContext = dataobject;
I can create one textblock with a working binding like this:
<TextBlock Text="Field1">
<TextBlock.Style>
<Style x:Key="HighlightStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.}" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
<TextBlock>
But I need to change the binding so that the style can be used on different TextBlocks. Something like:
<Style x:Key="HighlightStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.}" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</DataTrigger>
</Style.Triggers>
</Style>
<TextBlock Text="Field1" DataContext="{Binding Path=BooleanProperty1}" Style="{StaticResource HighlightStyle}"/>
<TextBlock Text="Field2" DataContext="{Binding Path=BooleanProperty2}" Style="{StaticResource HighlightStyle}"/>
When I try this, changing the properties does nothing to highlight the textblock. Is there a way to accomplish this?
Could always abuse the tag property.
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="Tag" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Field1" Grid.Row="0" Tag="{Binding Field1}"/>
<TextBlock Text="Field2" Grid.Row="1" Tag="{Binding Field2}"/>
</Grid>
</Window>
or if you're feeling adventurous you could create an attached dependency property and pass that over.
public class TextBlockExtender : DependencyObject
{
public static string GetMyDataField(DependencyObject obj)
{
return (string)obj.GetValue(MyDataFieldProperty);
}
public static void SetMyDataField(DependencyObject obj, string value)
{
obj.SetValue(MyDataFieldProperty, value);
}
public static readonly DependencyProperty MyDataFieldProperty =
DependencyProperty.RegisterAttached("MyDataField", typeof(string), typeof(TextBlockExtender), new PropertyMetadata(null));
}
used with XAML
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="local:TextBlockExtender.MyDataField" Value="True">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Foreground" Value="Black"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Text="Field1" Grid.Row="0" local:TextBlockExtender.MyDataField="{Binding Field1}"/>
<TextBlock Text="Field2" Grid.Row="1" local:TextBlockExtender.MyDataField="{Binding Field2}"/>
</Grid>
</Window>
I am new to WPF, and learning the basics of WPF. What I want is when a CheckBox is checked then make the background of a Button green.
The following is to code I have written:
<Window x:Class="MyApplication.DataTrigger2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataTrigger2" Height="300" Width="300" Loaded="Window_Loaded">
<Window.Resources>
<Style x:Key="styleDataButton" TargetType="Button">
<Style.Triggers>
<DataTrigger Binding="{Binding chk}" Value="checked">
<Setter Property="Background" Value="Gold"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="btn" Height="50" Width="100" Content="Button" Margin="89,33,89,178" Style="{StaticResource styleDataButton}"/>
<CheckBox x:Name="chk" Content="Checkbox" Height="50" Width="100" Margin="89,106,89,105"></CheckBox>
</Grid>
</Window>
You need to bind to CheckBox element. Binding="{Binding chk}" means that you are binding to "chk" property of the DataContext. You should change it to:
<DataTrigger Binding="{Binding ElementName=chk, Path=IsChecked}" Value="True">
<Setter Property="Background" Value="Gold"/>
</DataTrigger>
That way, you are binding to IsChecked property of your CheckBox and checking if value is true.
How to create a trigger, which if mouse hover that textblock, the text will change color.
just try this with background or foreground
<TextBlock Text="Hello" Height="20">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextBlock.Background" Value="red" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Window x:Class="WpfApplication1.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 x:Key="TextBlockMouseOverStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<TextBlock Background="Blue" Style="{StaticResource TextBlockMouseOverStyle}" Text="Foo" />
</Grid>
</Window>