how to bind to property without destroying the control template Features? - c#

I made a Control Template which it's target type if button.
Tow of it's event triggers is belong to the IsEnable and IsnotEnable property. when the control template is enable I made the opacity 100% and when its not I made the opacity go down to 40%.
in my GUI Window I defined a new button like this:
<Button x:Name="JoinB"
IsEnabled="{Binding Path=GroupStatus,Converter={StaticResource EnableConverter}}"
Template="{DynamicResource JoinButtonStyle}" />
EnableConverter is a simple Converter that return true or false.
The converter is working. My button does get not enable but the opacity doesn't change.
If i define my button like this (without the converter):
<Button x:Name="JoinB" IsEnabled="false"
Template="{DynamicResource JoinButtonStyle}" />
the opacity does change.
Do you have any idea what I am doing wrong?
JoinButtonStyle Code:
<ControlTemplate x:Key="JoinButtonStyle" TargetType="{x:Type Button}">
<ControlTemplate.Resources>
<Storyboard x:Key="OnMouseEnter1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.BlurRadius)" Storyboard.TargetName="rectangle">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="8"/>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.Color)" Storyboard.TargetName="rectangle">
<EasingColorKeyFrame KeyTime="0:0:0.2" Value="#FF00BC02"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnMouseLeave1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Effect).(DropShadowEffect.BlurRadius)" Storyboard.TargetName="rectangle">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="2"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnPreviewMouseLeftButtonDown1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0.7"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="label">
<EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0.7"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="OnPreviewMouseLeftButtonUp1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="rectangle">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="label">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="onNotEnabled">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0" Value="0.4"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="onEnabled">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="grid">
<EasingDoubleKeyFrame KeyTime="0" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="grid" VerticalAlignment="Center" HorizontalAlignment="Center" Background="#00000000">
<Rectangle x:Name="rectangle" HorizontalAlignment="center" VerticalAlignment="center" Height="30" Width="90" RadiusX="15" RadiusY="15" StrokeThickness="1" Stroke="#FF58A6FD">
<Rectangle.Effect>
<DropShadowEffect BlurRadius="2" ShadowDepth="0" Color="#FF58A6FD"/>
</Rectangle.Effect>
</Rectangle>
<Label x:Name="label" FontSize="15" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="#FF58A6FD" Content="Join"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="UIElement.PreviewMouseLeftButtonUp">
<BeginStoryboard x:Name="OnPreviewMouseLeftButtonUp1_BeginStoryboard" Storyboard="{StaticResource OnPreviewMouseLeftButtonUp1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="UIElement.PreviewMouseLeftButtonDown">
<BeginStoryboard x:Name="OnPreviewMouseLeftButtonDown1_BeginStoryboard" Storyboard="{StaticResource OnPreviewMouseLeftButtonDown1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<BeginStoryboard x:Name="OnMouseLeave1_BeginStoryboard" Storyboard="{StaticResource OnMouseLeave1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<BeginStoryboard x:Name="OnMouseEnter1_BeginStoryboard" Storyboard="{StaticResource OnMouseEnter1}"/>
</EventTrigger>
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard x:Name="OnMouseEnter1_BeginStoryboard1" Storyboard="{StaticResource onNotEnabled}"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="onEnabled_BeginStoryboard" Storyboard="{StaticResource onEnabled}"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
converter code:
public class EnableToGroupStatusConverter:IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((ClientManager.DateGroupInfo.GroupStatusType)value == ClientManager.DateGroupInfo.GroupStatusType.CLOSED)
{
return false;
}
else
{
return true;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
}

Instead of having two different Trigger for enabled/disabled state as you currently do
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource onNotEnabled}"/>
</Trigger.EnterActions>
</Trigger>
<Trigger Property="IsEnabled" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource onEnabled}"/>
</Trigger.EnterActions>
</Trigger>
combine them into one Trigger with EnterActions/ExitActions
<Trigger Property="IsEnabled" Value="False">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource onNotEnabled}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource onEnabled}"/>
</Trigger.ExitActions>
</Trigger>

Related

I added some animations on the button by style triggers, but the second animation on the same property doesn't work

Here is my XAML code.
<Window x:Class="TestWpf.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:local="clr-namespace:TestWpf"
mc:Ignorable="d"
Title="MainWindow" Height="320" Width="340">
<Window.Resources>
<QuadraticEase x:Key="easing" EasingMode="EaseOut"/>
</Window.Resources>
<Grid>
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Label Name="label"/>
<Button Content="Hello" Width="100" Height="45">
<Button.Style>
<Style TargetType="Button">
<Style.Resources>
<Storyboard x:Key="press" x:Name="press">
<DoubleAnimation Storyboard.TargetProperty="Width" To="125" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="50" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="hover" x:Name="hover">
<DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="leave" x:Name="leave">
<DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource press}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource leave}"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</Window>
You can see that I specified a style for the button, and added some triggers that can do some animation when I move the mouse or click the mouse button.
When I move my mouse to the button, the button size turns 120x45. But when I pressed the mouse button after that, nothing happened.
What I want:
Button default size is 100x45
When the mouse is hovering, the button size will change to 120x45 (width increased by 20) through animation, and when not hovering, the size will be restored
When the mouse is pressed, the size will change to 125x50 through animation (the width and height increase by 5), and when the mouse is released, the size will restore
even if I add StopStoryboard before BeginStoryboard, it will throw an exception that the Storyboard cannot be found.
I ran your XAML with these changes and everything works fine for me:
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
<Label x:Name="label" Content="LABEL"/>
<Button Content="Hello" Width="100" Height="45">
<Button.Style>
<Style TargetType="Button">
<Style.Resources>
<Storyboard x:Key="press" x:Name="press">
<DoubleAnimation Storyboard.TargetProperty="Width" To="200" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="100" Duration="0:0:0.100" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="hover" x:Name="hover">
<DoubleAnimation Storyboard.TargetProperty="Width" To="120" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.200" EasingFunction="{StaticResource easing}"/>
</Storyboard>
<Storyboard x:Key="leave" x:Name="leave">
<DoubleAnimation Storyboard.TargetProperty="Width" To="100" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
<DoubleAnimation Storyboard.TargetProperty="Height" To="45" Duration="0:0:0.300" EasingFunction="{StaticResource easing}"/>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<StopStoryboard BeginStoryboardName="IsMouseOverTrue"/>
<BeginStoryboard Storyboard="{StaticResource press}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource hover}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="IsMouseOverTrue" Storyboard="{StaticResource hover}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource leave}"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>

How to restart WPF animation/storyboard?

I have an hotkey that flashes a prompt text over the UI and then disappears. But the issue is, my storyboard flashes only once in its lifetime which also means it fires the Completed event once.
When I press the hotkey, the grid that holds the TextBlock becomes visible, but the animation no longer plays and the completed no longer fires.
I need those to work so that each time the grid becomes visible, the animation restarts from the start and then fires the completed event which will set the visibility of the grid to false.
Here is the code:
<Grid Visibility="{Binding InfoTextVisible, ElementName=MyMainWindow}">
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard Completed="InfoTextAnimation_Completed" FillBehavior="Stop">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="0:0:1" Completed="DoubleAnimationUsingKeyFrames_Completed">
<SplineDoubleKeyFrame KeyTime="0:0:00.00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:01.00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:01.50" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<TextBlock Text="{Binding InfoText, ElementName=MyMainWindow}" Name="timoti" Foreground="White" FontSize="50" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
New code:
<Grid Visibility="{Binding InfoTextVisible, ElementName=MyMainWindow}">
<Grid.Style>
<Style TargetType="Grid">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard x:Name="SpinStoryboard">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="0:0:1">
<SplineDoubleKeyFrame KeyTime="0:0:00.00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="0:0:01.00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="0:0:01.50" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0:0:02.00" Value="{x:Static Visibility.Hidden}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="SpinStoryboard"></StopStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding InfoText, ElementName=MyMainWindow}" Name="timoti" Foreground="White" FontSize="50" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>

Animatint BlurEffect in a style works but animating DropShadowEffect causes error?

I am trying to animate a DropShadowEffect I have applied to one grid and a BlurEffect that I have applied to another grid.
The blur animation seems to work fine and this is the code.
<Style x:Key="BluredGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="extentions:GridExtention.IsBlured" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).Radius" From="0" To="10" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).Radius" From="10" To="0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Grid Background="{DynamicResource BrHostBackground}">
<Grid extentions:GridExtention.IsBlured="{Binding BackgroundIsBlured}" Style="{StaticResource BluredGridStyle}">
<Grid.Effect>
<BlurEffect x:Name="BlurEffect" Radius="0"/>
</Grid.Effect>
</Grid>
</Grid>
But when I try with the drop shadow I get errors. Here is my initial code.
<Style x:Key="DropShaodowGridStyle" TargetType="{x:Type Grid}">
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).BlurRadius" From="0" To="80" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Effect).BlurRadius" From="80" To="0" Duration="0:0:0.2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Grid Visibility="{Binding HardwareLoadingVisibility}">
<Grid x:Name="grid" HorizontalAlignment="Center" VerticalAlignment="Center" Background="White" Width="550" Height="250" Style="{DynamicResource DropShaodowGridStyle}">
<Grid.Effect>
<DropShadowEffect ShadowDepth="0" Opacity="0.8"/>
</Grid.Effect>
</Grid>
</Grid>
This generates the following error
InvalidOperationException: Cannot resolve all property references in the property path '(Effect).BlurRadius'. Verify that applicable objects support the properties.
If I change the property to (Effect).Radius I get the same error.
I also tried changing the property to (UIElement.Effect).(DropShadowEffect.BlurRadius) which generated this error
InvalidOperationException: 'Effect' property does not point to a DependencyObject in path '(0).(1)'.
Looks like I found the answer.
I had to assign a default value to the property in the style.
<Style x:Key="DropShaodowBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" BlurRadius="0"></DropShadowEffect>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).BlurRadius" From="0" To="80" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(UIElement.Effect).BlurRadius" From="80" To="0" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>

Load all the effect of storyboard until it's finish

I have an image which when pressed by user, the opacity will fade until value 0. But the effect only continues if user press and hold the image. Is there a possible way to change the code to: When user press, and without holding the press, the opacity fading effect will stay? I wish to do it in XAML.
<EventTrigger RoutedEvent="Button.Click" SourceName="press">
<EventTrigger.Actions>
<BeginStoryboard Storyboard="{StaticResource showA}"/>
</EventTrigger.Actions>
</EventTrigger>
<Button Grid.Column="5" Command="{Binding Path=PressC}" CommandParameter="dot" Style="{StaticResource TransparentButton}">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Image Name="image5" Source="/W;component/Images/t.png" Height="100" />
<Image Name="pressed5" Source="/W;component/Images/T.png" Height="100" Width="200" Margin="-23,-136,-21,0" Visibility="Hidden" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="pressed5" Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Setter Property="Panel.ZIndex" Value="999"/>
<Setter TargetName="pressed5" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
Can you show your full xaml? Because Image does not have IsPressed property and it is not clear how it works for you.
Similar code for button works as expected:
<Button Background="Aquamarine">
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
And for Image it works too with EventTrigger:
<Image Source="d:\123.png">
<Image.Style>
<Style TargetType="Image">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseDown">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" From="1" To="0"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Image.Style>

Multiple storyboards on one property

I have multiple storyboards that access the same property (not at the same time). After one storyboard changed the property, the other one seems to have no access to it and does not change anything.. What can I do against this?
Sample:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border Name="Border" BorderBrush="DarkGray" BorderThickness="1" Margin="3">
<ContentPresenter />
<Border.Background>
<SolidColorBrush />
</Border.Background>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="#3e8bff" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True" />
<Condition Property="IsSelected" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Orange" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</MultiTrigger.ExitActions>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>hey</sys:String>
<sys:String>du</sys:String>
<sys:String>dux</sys:String>
<sys:String>duy</sys:String>
<sys:String>dua</sys:String>
</ListBox.Items>
</ListBox>
This is the smallest sample code I could make. After you've hovered an item, it won't turn blue when it's selected (try to click on one item and then use the arrow keys to select items without hovering them).
I have a solution!!! Triggers and actions order does matter... the answer is not to play more then one storyboard at the same time, just stop other.
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="Selector.IsSelected" Value="False" />
</MultiTrigger.Conditions>
<MultiTrigger.EnterActions>
<StopStoryboard BeginStoryboardName="SelectedBegin" />
<StopStoryboard BeginStoryboardName="UnselectBegin" />
<BeginStoryboard x:Name="EnterBegin" Storyboard="{StaticResource MouseEnterSb}"/>
</MultiTrigger.EnterActions>
<MultiTrigger.ExitActions>
<BeginStoryboard x:Name="LeaveBegin" Storyboard="{StaticResource MouseLeaveSb}"/>
</MultiTrigger.ExitActions>
</MultiTrigger>
<Trigger Property="Selector.IsSelected" Value="True">
<Trigger.EnterActions>
<StopStoryboard BeginStoryboardName="LeaveBegin" />
<StopStoryboard BeginStoryboardName="EnterBegin" />
<BeginStoryboard x:Name="SelectedBegin" Storyboard="{StaticResource SelectedSb}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard x:Name="UnselectBegin" Storyboard="{StaticResource UnselectSb}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
I've been able to reproduce your erroneous results using the following code (I'm stumped too):
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ControlTemplate.Resources>
<Storyboard x:Key="BorderAnimationToRed">
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Red" Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Key="BorderAnimationToBlue">
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Blue" Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Key="BorderAnimationToOrange">
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="Orange" Duration="0:0:0.1" />
</Storyboard>
<Storyboard x:Key="BorderAnimationToWhite">
<ColorAnimation Storyboard.TargetName="Border" Storyboard.TargetProperty="Background.Color" To="White" Duration="0:0:0.1" />
</Storyboard>
</ControlTemplate.Resources>
<Border Name="Border" BorderBrush="DarkGray" BorderThickness="1" Margin="3">
<ContentPresenter />
<Border.Background>
<SolidColorBrush />
</Border.Background>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BorderAnimationToOrange}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource BorderAnimationToWhite}"/>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource BorderAnimationToBlue}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource BorderAnimationToWhite}"/>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Items>
<sys:String>hey</sys:String>
<sys:String>du</sys:String>
<sys:String>dux</sys:String>
<sys:String>duy</sys:String>
<sys:String>dua</sys:String>
</ListBox.Items>
This code is a little easier to read, as the visuals, resources, and triggers are declared separately. Maybe you could try to use EventTriggers to accomplish your goal (using the "ListBoxItem.MouseEnter" and "ListBoxItem.MouseLeave" routed events). Good luck!

Categories