[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.
Related
I'm working on a WPF application. I have a button, which contains a Grid with a TextBlock and a Path element, as following:
<Button x:Name="btn" Margin="1">
<Button.Content>
<Grid Style="{DynamicResource button_special_hover}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="15*" />
</Grid.ColumnDefinitions>
<TextBlock x:Name="tx" TextWrapping="Wrap" Text="{DynamicResource MenuString}" Grid.Column="2" />
<Path x:Name="path" Stretch="Fill" Fill="{DynamicResource MarkerBrush}" Data="M 65.3334,41.3334C 65.3334,45.0133 62.3467,48 58.6667" Grid.Column="0" />
</Grid>
</Button.Content>
What I want to achieve is that once I hover the grid inside the button with my mouse, I want the foreground of the text inside the textblock to turn into white and the fill color for the path element to turn into white too.
What I've tried to do is declare a style for the grid as following: (button_special_hover)
<Style x:Key="button_special_hover" TargetType="{x:Type Grid}">
<Setter Property="Background" Value="Transparent"/>
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},
Path=IsMouseOver}" Value="True">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},
Path=IsMouseOver}" Value="True">
<Setter Property="Fill" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
I don't get what I want. Once I hover over the grid, nothing happens. Only when I hover the Textblock inside the grid, the text turns into White. Once I hover the Path, nothing happens.
How can I achieve that once I hover the grid both the textblock foreground and the Path Fill turn into White? Thanks!
Your problem is that you specified the fill on the path element.
NOTE: I 'fixed' the Data by added ",41.3334" to it.
<Path x:Name="path" Stretch="Fill" Fill="{DynamicResource MarkerBrush}" Data="M 65.3334,41.3334C 65.3334,45.0133 62.3467,48 58.6667,41.3334" Grid.Column="0" />
When you do that, you can't override it. If you specified it in the style instead then you'd get the results you want.
Remove Fill from Path:
<Path x:Name="path" Stretch="Fill" Data="M 65.3334,41.3334C 65.3334,45.0133 62.3467,48 58.6667,41.3334" Grid.Column="0" />
and add Fill to the style:
<Style x:Key="button_special_hover" TargetType="{x:Type Grid}">
<Setter Property="Background" Value="Transparent"/>
<Style.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},
Path=IsMouseOver}" Value="True">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type Path}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},
Path=IsMouseOver}" Value="True">
<Setter Property="Fill" Value="White"/>
</DataTrigger>
</Style.Triggers>
<!-- "All I did was add this line below" -->
<Setter Property="Fill" Value="{DynamicResource MarkerBrush}"/>
</Style>
</Style.Resources>
</Style>
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>
I am new to XAML and WPF.
On Button press I want to change the canvas drawn on the button from ic_maximize to ic_restore and switch the canvas when the button is pressed again. I am using the mahapps library. Can you please tell me how to go about doing this?
I have tried a lot of different StackOverflow links, but none of them are pertinent to my problem.
Here is the style for my maximize button. I have the "IsPressed" triggers ready but not able to figure out what need to be set when it is triggered.-
<Canvas x:Key="ic_maximize" Width="13.3333" Height="13.3333" Canvas.Left="0" Canvas.Top="0">
<Rectangle Width="11.7333" Height="11.7333" Canvas.Left="2.136" Canvas.Top="-0.536002" Stretch="Fill" StrokeThickness="1.06667" StrokeLineJoin="Round" Stroke="#FF999999"/>
<Rectangle Width="11.7333" Height="11.7333" Canvas.Left="5.36442e-007" Canvas.Top="1.6" Stretch="Fill" StrokeThickness="1.06667" StrokeLineJoin="Round" Stroke="#FF999999" Fill="#FF161616"/>
</Canvas>
<Canvas x:Key="ic_restore" Width="12" Height="12" Canvas.Left="0" Canvas.Top="0">
<Rectangle Width="11.7333" Height="11.7333" Canvas.Left="5.36442e-007" Canvas.Top="0.266666" Stretch="Fill" StrokeThickness="1.06667" StrokeLineJoin="Round" Stroke="#FF999999"/>
</Canvas>
<Style x:Key="ExtendedMaxButtonStyle"
TargetType="{x:Type Button}"
BasedOn="{StaticResource MetroWindowButtonStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Name="grid" Background="{StaticResource MaxButton.Grid.background}">
<!-- either one of the ic_maximize/ic_restore canvases should come here -->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="grid" Property="Background" Value="{StaticResource MaxButton.MouseOver.Background}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<!-- What should I write here?-->
</Trigger>
<Trigger Property="IsPressed" Value="False">
<!-- What should I write here?-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Place both Canvas on top of each other, and hide one upon IsPressed.
<Grid Name="grid">
<Canvas Background="Purple">
<Canvas.Style>
<Style TargetType="Canvas">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Canvas.Style>
<TextBlock Text="ic_max" FontSize="48"/>
</Canvas>
<Canvas Background="Green">
<Canvas.Style>
<Style TargetType="Canvas">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource Mode=TemplatedParent}}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Canvas.Style>
<TextBlock Text="ic_restore" FontSize="48"/>
</Canvas>
</Grid>
Hi I was wondering is there a way to only edit the Dock Ability Arrows on the Dock Guide for a docking manager using syncfusion for wpf? I can edit the complete style of the docking manager but I only want the ability to edit the arrows as I have the theme in a specific way but need the arrows only to be different is this possible at all? And if so how can I access it?
To do this you need to edit the Drag Provider Templates below is some XAML example for anyone who has a similar problem or was curious as to how to do it
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<!-- Control template for TopDragProvider -->
<ControlTemplate x:Key="TopDragProviderTemplate" TargetType="{x:Type ContentControl}">
<Image Name="Img" Width="29" Height="32" Syncfusion:DockPreviewManagerVS2005.ProviderAction="GlobalTop" Source="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalTop.png" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSideButtonActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Syncfusion:DockPreviewMainButtonVS2005}}}" Value="true">
<Setter TargetName="Img" Property="Source" Value="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalTopOver.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Control template for LeftDragProvider -->
<ControlTemplate x:Key="LeftDragProviderTemplate" TargetType="{x:Type ContentControl}">
<Image Name="Img" Width="32" Height="29" Syncfusion:DockPreviewManagerVS2005.ProviderAction="GlobalLeft" Source="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalLeft.png" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSideButtonActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Syncfusion:DockPreviewMainButtonVS2005}}}" Value="true">
<Setter TargetName="Img" Property="Source" Value="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalLeftOver.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Control template for RightDragProvider -->
<ControlTemplate x:Key="RightDragProviderTemplate" TargetType="{x:Type ContentControl}">
<Image Name="Img" Width="32" Height="29" Syncfusion:DockPreviewManagerVS2005.ProviderAction="GlobalRight" Source="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalRight.png" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSideButtonActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Syncfusion:DockPreviewMainButtonVS2005}}}" Value="true">
<Setter TargetName="Img" Property="Source" Value="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalRightOver.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- Control template for BottomDragProvider -->
<ControlTemplate x:Key="BottomDragProviderTemplate" TargetType="{x:Type ContentControl}">
<Image Name="Img" Width="29" Height="32" Syncfusion:DockPreviewManagerVS2005.ProviderAction="GlobalBottom" Source="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalBottom.png" />
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSideButtonActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Syncfusion:DockPreviewMainButtonVS2005}}}" Value="true">
<Setter TargetName="Img" Property="Source" Value="pack://application:,,,/Syncfusion.Tools.WPF;component/Framework/DockingManager/Resources/DockPreviewVS2005GlobalBottomOver.png"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
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.