Handle Custom RoutedEvent in Event Trigger - c#

I have the following tree
MainWindow -> Custom UserControl -> GroupBox -> ViewBox
I've added a Custom Routed Event to the UserControl, as :
public static readonly RoutedEvent ConnectedEvent =
EventManager.RegisterRoutedEvent("Connected", RoutingStrategy.Tunnel,
typeof(RoutedEventHandler), typeof(IQMasterControl));
public event RoutedEventHandler Connected
{
add { AddHandler(IQMasterControl.ConnectedEvent, value); }
remove { RemoveHandler(IQMasterControl.ConnectedEvent, value); }
}
The invocation of the event is following:
_masterViewModel.Connected += delegate ()
{
RoutedEventArgs ea = new RoutedEventArgs(IQMasterControl.ConnectedEvent, this);
this.RaiseEvent(ea);
};
I want to run some animation on ViewBox on "Connected" event using Event Trigger:
<Viewbox VerticalAlignment="Center"
Child="{StaticResource PDataIco}"
RenderTransformOrigin="0.5, 0.5" Stretch="Uniform">
<Viewbox.RenderTransform>
<!-- the transform a name tells the framework not to freeze it -->
<RotateTransform x:Name="noFreeze" />
</Viewbox.RenderTransform>
<Viewbox.Triggers>
<EventTrigger RoutedEvent="local:IQMasterControl.Connected">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewbox.Triggers>
</Viewbox>
I have checked that the event is raised, but ViewBox does not seem to be receiving the event. So, no animation is started.
If I change the RoutedEvent property of the EventTrigger to another (f.e. Loaded) the animation works fine.
Can anyone help me on this?

You are raising the event for the UserControl.
It is not raised for the ViewBox.
There are two ways to go:
Both require adding name for the ViewBox:
<Viewbox VerticalAlignment="Center" x:Name="ViewBox"
Child="{StaticResource PDataIco}"
RenderTransformOrigin="0.5, 0.5" Stretch="Uniform">
<Viewbox.RenderTransform>
<!-- the transform a name tells the framework not to freeze it -->
<RotateTransform x:Name="noFreeze" />
</Viewbox.RenderTransform>
<Viewbox.Triggers>
<EventTrigger RoutedEvent="local:IQMasterControl.Connected">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation RepeatBehavior="Forever" Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Viewbox.Triggers>
</Viewbox>
1.Raise it for the ViewBox:
_masterViewModel.Connected += delegate ()
{
RoutedEventArgs ea = new RoutedEventArgs(IQMasterControl.ConnectedEvent, this);
ViewBox.RaiseEvent(ea);
};
OR
2.Handle it in UserControl:
<UserControl.Triggers>
<EventTrigger RoutedEvent="local:IQMasterControl.Connected">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation RepeatBehavior="Forever" Storyboard.Target="{Binding ElementName=Viewbox}" Storyboard.TargetProperty="(Rectangle.RenderTransform).(RotateTransform.Angle)" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</UserControl.Triggers>

Related

Animate grid background color using storyboard in WPF

I'm new to WPF storyboard. I want to animate grid background color. I'm getting this error:
System.InvalidOperationException: 'Cannot resolve all property
references in the property path 'Background.Color'. Verify that
applicable objects support the properties.'
My XAML code:
<Grid x:Name="alert_grid">
<Grid.Resources>
<Storyboard x:Key="flashing_storyboard" Storyboard.TargetName="alert_grid">
<ColorAnimation
Storyboard.TargetProperty="Background.Color"
From="Black" To="Orange" Duration="0:0:2"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</Grid.Resources>
</Grid>
Code behind:
Storyboard sb = alert_grid.FindResource("flashing_storyboard") as Storyboard;
if (sb != null)
{
sb.Begin();
}
Any idea how to get the background color animated?
Please try this.
<Grid Name="alert_grid" Height="75" HorizontalAlignment="Left" Margin="27,12,0,0" VerticalAlignment="Top" Width="160" Background="LightGray">
<Grid.Triggers>
<EventTrigger RoutedEvent="Button.MouseLeave">
<BeginStoryboard>
<Storyboard x:Name ="flashing_storyboard" Storyboard.Target="{Binding ElementName=alert_grid}">
<ColorAnimation To="Orange" Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)" From="Black"
AutoReverse="True" RepeatBehavior="Forever" FillBehavior="Stop" Duration="0:0:2"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
</Grid>
and code behind
Storyboard sb = alert_grid.FindName("flashing_storyboard") as Storyboard;
if (sb != null)
{
sb.Begin();
}

First WPF animation then run the code in Screen ViewModel

Hello I have a question I want to do this animation then when the animation is completed I would like to run the code and I can't figure it out the way to do it in MVVM using CaliburnMicro.
Please help me if possible.
<Button x:Name="Forgot">
<Button.RenderTransform>
<TranslateTransform />
</Button.RenderTransform>
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="UserName"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
From="0" To="-1000" Duration="0:0:1" />
<DoubleAnimation Storyboard.TargetName="Password"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
From="0" To="-1000" Duration="0:0:1" />
<DoubleAnimation Storyboard.TargetName="LogIn"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
From="0" To="-1000" Duration="0:0:1" />
<DoubleAnimation Storyboard.TargetName="Forgot"
Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)"
From="0" To="-1000" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
You should listen to the Completed event a StoryBoard raises once the animations finishes.
You can either use an EventTrigger for that (though I am not certain if that will work) or bind a handler in XAML and do whatever you like at that point.
Update:
XAML:
<Storyboard Completed="storyboard_Completed">
...
C#:
void storyboard_Completed(object sender, EventArgs args)
{
// Do whatever you want here.
}
I did it like this.
private void DoubleAnimation_Completed(object sender, EventArgs e)
{
LoginViewModel vm = this.DataContext as LoginViewModel;
vm.Forgot();
}
and now it works. thank you

StatusBar text fade-out when binding using Caliburn.Micro

In my ShellViewModel I have the following property:
private string _status = "";
public string Status
{
get
{
return _status;
}
set
{
_status = value;
NotifyOfPropertyChange(() => Status);
}
}
In the ShellView I've named my StatusBar TextBlock "Status" so that it binds to the above using Caliburn.Micro - and it does.
Then I've tried to add a "StoryBoard" element so that after a short amount of time the text fades away - currently the text appears but does not fade away - how do I fix this?
<StatusBar DockPanel.Dock="Bottom">
<TextBlock x:Name="Status">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:0"
To="1.0" />
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:2"
From="1.0"
To="0.0"
BeginTime="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</StatusBar>
You would need two changes,
First, you need to update the binding to Raise the TargetUpdated Event when property changes. This can be done using Binding.NotifyOnTargetUpdated
<TextBlock Text="{Binding Status, NotifyOnTargetUpdated=True}">
Then, your BeginTime is higher than the Duration in the second animation (BeginTime="0:0:5" ), which needs to be corrected.
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:2" From="1.0" To="0.0" BeginTime="0:0:0.5" />
Complete Code
<TextBlock Text="{Binding Status, NotifyOnTargetUpdated=True}">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="Binding.TargetUpdated">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:0" To="1.0" BeginTime="0:0:0.5"/>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
Duration="0:0:2" From="1.0" To="0.0" BeginTime="0:0:0.5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>

Invoking animation in a different xaml control on button click WITHOUT resorting to ViewModels

I have the following xaml:
<Button Content="{Binding Header}" Background="Blue" Name="PanelHeader">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Stackpanel"
Storyboard.TargetProperty="Height"
From="0" To="100" Duration="0:0:3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
I want to move the storyboard animation to the stack panel declaration and simply invoke that animation from the button click.
Most examples I've found resort to using the viewmodel or other codebehind interjections.
this example doesn't use code behind nor ViewModel
http://www.java2s.com/Tutorial/VB/0290__Windows-Presentation-Foundation/StartandstopanAnimationwithButtonactions.htm

How to Pause a Storyboard on MouseEnter and Resume on MouseExit

I have a scrolling news ticker that is animated via a Storyboard. It currently works pretty well but I would like to pause it whenever the Mouse is over the TextBlock and then have it resume once the mouse is moved off of the TextBlock
<WrapPanel x:Name="Ticker" >
<TextBlock Text="{Binding NewsTicker, IsAsync=True}" FontSize="18" Foreground="White" >
<TextBlock.RenderTransform>
<TranslateTransform x:Name="translate" />
</TextBlock.RenderTransform>
<TextBlock.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="NewsTicker">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation From="{Binding ElementName=Ticker, Path=ActualWidth}" To="{Binding ElementName=Ticker, Path=ActualWidth, Converter={StaticResource NegConverter}}" Storyboard.TargetName="translate" Storyboard.TargetProperty="X" Duration="0:0:35" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.EnterActions>
<PauseStoryboard BeginStoryboardName="NewsTicker" />
</EventTrigger.EnterActions>
<EventTrigger.ExitActions>
<ResumeStoryboard BeginStoryboardName="NewsTicker" />
</EventTrigger.ExitActions>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</WrapPanel>
I've tried several combinations of Pause and Resume Storyboard as well as different RoutedEvents. I even removed the EventTrigger.ExitAction just to see if the pause would work but it made no difference.
Instead of using EnterActions/ExitActions use MouseEnter and MouseLeave events
<TextBlock.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard x:Name="NewsTicker">
<Storyboard RepeatBehavior="Forever">
<DoubleAnimation ... />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseEnter">
<PauseStoryboard BeginStoryboardName="NewsTicker" />
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<ResumeStoryboard BeginStoryboardName="NewsTicker" />
</EventTrigger>
</TextBlock.Triggers>
since events don't have state there is no enter/exit action there is just action when event occurs
EventTrigger Class
Trigger objects have the Setters, EnterActions, and ExitActions properties that apply changes or actions based on the state of certain properties, while EventTrigger objects start a set of Actions when a specified routed event occurs

Categories

Resources