I am working on a WPF application and I would like to change the visibility of a grid if an only if a button has focus. I have the following code to change the background of the button if it has focus. I know how to do this Programmatically, but I'd like to know how to get the same thing done in XAML.
<Style TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
You can name your Button and use a DataTrigger:
<Window
...
>
<Window.Resources>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<Button x:Name="butt">Hide</Button>
<Grid>
<Label Background="Yellow">Inside Grid</Label>
</Grid>
<Button>Steal focus</Button>
</StackPanel>
</Window>
EDIT
<Window
...
>
<Window.Resources>
<Style x:Key="CollapsedGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=butt}" Value="True">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ToggleButton x:Name="butt">Hide</ToggleButton>
<Grid x:Name="GridA"
Style="{StaticResource CollapsedGridStyle}">
<Label Background="Yellow">Grid A</Label>
</Grid>
<Grid x:Name="GridB">
<Label Background="Green">Grid B</Label>
</Grid>
</StackPanel>
</Window>
Related
following is the code, which is showing the error i.e
: The content property is more than once
Code :
<Window x:Class="Trigger.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">
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<Grid>
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>
</Window>
The Window element can host only one child. You need to put the Style in the resources. Something like this will do:
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Put this right after the starting tag of the Window element or just before the closing tag of the Window element.
The full code should be like this:
<Window x:Class="Trigger.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="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>
</Window>
Add style inside Window.Resources
<Window.Resources>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.5" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid >
<Button x:Name="PropertyTriggerButton" Width="160" Height="40" Margin="20,0,0,0" HorizontalAlignment="Left" Content="IsPressed Property"
Cursor="Hand" FontWeight="Bold" Style="{StaticResource ButtonStyle}" ToolTip="Press To Raise Property Trigger">
</Button>
</Grid>
I have a style defined in my resource dictionary so the style can be used in all over my application.
<Style x:Key="HyperlinkStyle" TargetType="{x:Type Hyperlink}">
<Setter Property="Foreground" Value="{StaticResource Color3}" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="TextBlock.TextDecorations" Value="{x:Null}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource Color3Pressed}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{StaticResource Color2NotEnabled}" />
</Trigger>
</Style.Triggers>
</Style>
I use the style in Datagrid like this :
<DataGridTemplateColumn Width="140*" CanUserReorder="False" CanUserResize="True" Header="">
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate />
</DataGridTemplateColumn.CellEditingTemplate>
<DataGridTemplateColumn.CellStyle>
<Style TargetType="DataGridCell" BasedOn="{StaticResource DatagridCellHyperlinkStyle}">
<Setter Property="IsEnabled" Value="{Binding Path=MyObject, Converter={StaticResource ConverterMyObject}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border Padding="{TemplateBinding Padding}" VerticalAlignment="Center">
<TextBlock Width="Auto" Height="Auto" TextTrimming="CharacterEllipsis">
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<InlineUIContainer TextDecorations="{Binding Path=TextDecorations, RelativeSource={RelativeSource AncestorType=TextBlock}}" Foreground="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType=TextBlock}}">
<ContentPresenter Width="Auto" Height="Auto" Content="{Binding DataContext.MyObject.Name, RelativeSource={RelativeSource AncestorType=DataGridRow}}"/>
</InlineUIContainer>
<Hyperlink.Style>
<Style TargetType="Hyperlink" BasedOn="{StaticResource HyperlinkStyle}">
<EventSetter Event="Hyperlink.Click" Handler="Clic" />
</Style>
</Hyperlink.Style>
</Hyperlink>
</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGridTemplateColumn.CellStyle>
</DataGridTemplateColumn>
This works great but I would like to be able to have 2 colors in my style depending on a parameter.
For example, my datagrid has 1500 rows, I want to highlight 100 rows from the collection by changing their hyperlink color.
So I thought the best was to set the Tag property of the hyperlink to a custom value and use it in the style. Following this answer : https://social.msdn.microsoft.com/Forums/vstudio/en-US/d3424267-ed1f-4b30-90a1-5cca9843bd22/problem-making-a-trigger-on-the-tag-property?forum=wpf, I made the changes below :
xmlns:sys="clr-namespace:System;assembly=mscorlib"
First I've set the tag manually for each row to see if the style changes :
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
and added this trigger to my hyperlink's style:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte> <!-- My highlighted object -->
</Trigger.Value>
<Setter Property="Foreground" Value="{StaticResource Color1}" />
</Trigger>
But it doesn't work when I launch my application (I still have "Color3" whereas I want "Color1" when Tag is equals to 10.
I've checked the output there isn't any error.
I've tried to change "sys:Byte" by "sys:String" but the result was the same.
Do I need to change my approach for this problem ? I've read maybe we can't add trigger on Tag Property.
Thank you
I suggest if you set the tag like this
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}" Tag="10">
Then write the trigger in the same way:
<Trigger Property="Tag" Value="10">
...setter
</Trigger>
Or if in hyperlink you use Byte type as Tag:
<Hyperlink IsEnabled="{TemplateBinding IsEnabled}">
<Hyperlink.Tag>
<sys:Byte>10</sys:Byte>
</Hyperlink.Tag>
</Hyperlink>
Then same goes in the trigger:
<Trigger Property="Tag">
<Trigger.Value>
<sys:Byte>10</sys:Byte>
</Trigger.Value>
...setter
</Trigger>
I am pretty new to WPF and I am trying to build a quite simple application using MVVM light.
In my MainWindow.xaml (view) I have this :
<ListBox ItemsSource="{Binding InstalledVersions}"
ItemTemplate="{StaticResource VersionsDataTemplate}"
Style="{StaticResource VersionsStyle}"
ItemContainerStyle="{StaticResource VersionItemStyle}"/>
Where InstalledVersions is a list of InstalledVersionViewModel
In my MainWindowResources.xaml I have this (simplified) :
<DataTemplate x:Key="VersionsDataTemplate"
DataType="{x:Type viewmodels:InstalledVersionViewModel}">
<Grid>
<TextBlock Text="{Binding VersionNumber}" />
<TextBlock Text="{Binding FolderPath}" />
</Grid>
</DataTemplate>
<Style x:Key="VersionsStyle"
TargetType="{x:Type ListBox}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Center" />
</Style>
<Style x:Key="VersionItemStyle"
TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="White" />
</Style>
I wish to have a different background depending on the "IsActive" property of my InstalledVersionViewModel.
I tried to add this (as well as several variations of it) to my VersionItemStyle but (as I suspected, mostly because I don't understand what I'm doing) it doesn't work :
<Style.Triggers>
<Trigger Property="{Binding Path=DataContext.IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type viewmodels:InstalledVersionViewModel}}}" Value="True">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
Thanks !
Since IsActive is part of view model against each row you can achieve that with DataTrigger
<Style x:Key="VersionItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="True">
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
Im coming from a C# winforms background and I would normally do all this in code.
I have several Labels that I'm using as a menu.
When the mouse hovers over them the text changes color by:
<Page.Resources>
<SolidColorBrush x:Key="normalColor" Color="White" />
<SolidColorBrush x:Key="mouseOverColor" Color="Gold" />
<Style TargetType="Label" x:Key="menuItemStyle">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Foreground" Value="{StaticResource normalColor}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{StaticResource mouseOverColor}"/>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Label x:Name="Label_Video1" Style="{StaticResource menuItemStyle}" Content="1.Video 1." FontSize="16" HorizontalAlignment="Left" Margin="25,74,0,0" VerticalAlignment="Top" MouseLeftButtonDown="Label_Video1_MouseLeftButtonDown" />
<Label x:Name="Label_Video2" Style="{StaticResource menuItemStyle}" Content="2. Video 2." FontSize="16" HorizontalAlignment="Left" Margin="25,105,0,0" VerticalAlignment="Top" MouseDown="Label_Video2_MouseDown"/>
When the user clicks a label I want it to stay a certin color (In this case Gold) and all the others to stay their normal colour. So if a label has been previously clicked and I click another label it will go from gold to white etc
When using WPF, you have to think slightly differently. We know that the Label control doesn't know when it has been clicked and it especially doesn't know when another Label element has been clicked... but some controls do. Thinking about it... a RadioButton has exactly this behaviour. Now this is where WPF really shines.
We can use RadioButtons and by providing them with a new ControlTemplate, we can make them look like plain text:
<Grid Background="Black">
<Grid.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<TextBlock Text="{TemplateBinding Content}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="White" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, RelativeSource={RelativeSource AncestorType={
x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource
AncestorType={x:Type RadioButton}}}" Value="True">
<Setter Property="Foreground" Value="Gold" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<StackPanel Margin="5" Background="{x:Null}">
<RadioButton Content="1.Video 1." />
<RadioButton Content="2.Video 2." />
<RadioButton Content="3.Video 3." />
</StackPanel>
</Grid>
If you don't want the RadioButtons to be all together in a StackPanel, then you can use give them the same GroupName property value to ensure that they still operate as one group.
[EDIT] *I had forgotten to include the Exception returned
'System.Windows.Style' is not a valid value for property 'Fill'*
This is my first post, I've already done lots of searching for questions where this might have already been answered to no success. I'm a complete noob when it comes to MVVM, Prism, and WPF and I have been thrown in the deep end on this one.
I wish to change the contents of 2 rectangles depending on a boolean in the Model (Binding Passed).
if a test returns Pass (bool True) then we display colour Green for first rectangle, and the second rectangle will display the UserControl.Resource Style x:Key="RectanglePass".
If test fails, then first rectangle is red, and second displays UserControl.Resource Style x:Key="RectangleFail"
I have the following xaml code:
<UserControl x:Class="Integration.Memjet.Aoqc.Views.ProcessResultView"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="RectangleFail" TargetType="Rectangle">
<Setter Property="Fill">
<Setter.Value>
<VisualBrush>
....
</VisualBrush>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RectanglePass" TargetType="Rectangle">
<Setter Property="Fill">
<Setter.Value>
<VisualBrush>
....
</VisualBrush>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition Height="60"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="20">PASS</Label>
<Rectangle Name="rectStatus" Grid.Row="1">
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Passed}" Value="True">
<Setter Property="Fill" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding Passed}" Value="False">
<Setter Property="Fill" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
<Rectangle Name="rectStatusImg" Width="120" Height="120" Grid.Row="2" >
<Rectangle.Style>
<Style TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding Passed}" Value="True">
<Setter Property="Fill" Value="{StaticResource RectanglePass}" />
</DataTrigger>
<DataTrigger Binding="{Binding Passed}" Value="False">
<Setter Property="Fill" Value="{StaticResource RectangleFail}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
</Rectangle>
</Grid>
</UserControl>
The above doesn't work and returns an exception.
If I was to replace the second Rectangle tag (rectStatusImg) with this line;
<Rectangle Name="rectStatusImg" Style="{StaticResource RectanglePass}" Width="120" Height="120" Grid.Row="2" ></Rectangle>
the xaml works and produces the expected result! But I wish to bind it to the Boolean Passed so I can change it programmatically.
I really hope I was able to explain my problem here.
Thank you for your help in advance, this site has always been a treasure and a great help.
Cheers,
Simon
define two visual brushes in your resource and create a style of rectangle with data trigger like
<VisualBrush x:Key="FailBrush">Black</VisualBrush>
<VisualBrush x:Key="PassBrush">Red</VisualBrush>
<Style x:Key="ColorRectangleStyle" TargetType="Rectangle">
<Setter Property="Fill" Value="{StaticResource FailBrush}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Passed}" Value="False">
<Setter Property="Fill" Value="{StaticResource PassBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
and use it in rectangle like
<Rectangle Name="rectStatusImg" Width="120" Height="120" Grid.Row="2" Style="{StaticResource ColorRectangleStyle}" />
Hope it helps.