I'm trying to trigger a progress animation when ever the ViewModel/Presentation Model is Busy. I have an IsBusy Property, and the ViewModel is set as the DataContext of the UserControl. What is the best way to trigger a "progressAnimation" storyboard when the IsBusy property is true? Blend only lets me add event triggers at the UserControl level, and I can only create property triggers in my data templates.
The "progressAnimation" is defined as a resource in the user control.
I tried adding the DataTriggers as a Style on the UserControl, but when I try to start the StoryBoard I get the following error:
'System.Windows.Style' value cannot be assigned to property 'Style' of object'Colorful.Control.SearchPanel'. A Storyboard tree in a Style cannot specify a TargetName. Remove TargetName 'progressWheel'.
ProgressWheel is the name of the object I'm trying to animate, so removing the target name is obviously NOT what I want.
I was hoping to solve this in XAML using data binding techniques, instead of having to expose events and start/stop the animation through code.
A trigger basically enables you to change property values or take actions based on the value of a property. So, it allows you to dynamically change the appearance and/or behavior of your control without having to create a new one.
Storyboard objects use name scopes to resolve the TargetName property. For more information about WPF name scopes, see WPF XAML Namescopes. If the TargetName property is omitted, the animation targets the element on which it is defined, or, in the case of styles, the styled element.
This example shows how to use a WPF animation to animate the value of a dependency property. It uses a DoubleAnimation, which is a type of animation that generates Double values, to animate the Opacity property of a Rectangle.
What you want is possible by declaring the animation on the progressWheel itself: The XAML:
<UserControl x:Class="TriggerSpike.UserControl1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="300" Width="300"> <UserControl.Resources> <DoubleAnimation x:Key="SearchAnimation" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:4"/> <DoubleAnimation x:Key="StopSearchAnimation" Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:4"/> </UserControl.Resources> <StackPanel> <TextBlock Name="progressWheel" TextAlignment="Center" Opacity="0"> <TextBlock.Style> <Style> <Style.Triggers> <DataTrigger Binding="{Binding IsBusy}" Value="True"> <DataTrigger.EnterActions> <BeginStoryboard> <Storyboard> <StaticResource ResourceKey="SearchAnimation"/> </Storyboard> </BeginStoryboard> </DataTrigger.EnterActions> <DataTrigger.ExitActions> <BeginStoryboard> <Storyboard> <StaticResource ResourceKey="StopSearchAnimation"/> </Storyboard> </BeginStoryboard> </DataTrigger.ExitActions> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> Searching </TextBlock> <Label Content="Here your search query"/> <TextBox Text="{Binding SearchClause}"/> <Button Click="Button_Click">Search!</Button> <TextBlock Text="{Binding Result}"/> </StackPanel>
Code behind:
using System.Windows; using System.Windows.Controls; namespace TriggerSpike { public partial class UserControl1 : UserControl { private MyViewModel myModel; public UserControl1() { myModel=new MyViewModel(); DataContext = myModel; InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { myModel.Search(myModel.SearchClause); } } }
The viewmodel:
using System.ComponentModel; using System.Threading; using System.Windows; namespace TriggerSpike { class MyViewModel:DependencyObject { public string SearchClause{ get;set;} public bool IsBusy { get { return (bool)GetValue(IsBusyProperty); } set { SetValue(IsBusyProperty, value); } } public static readonly DependencyProperty IsBusyProperty = DependencyProperty.Register("IsBusy", typeof(bool), typeof(MyViewModel), new UIPropertyMetadata(false)); public string Result { get { return (string)GetValue(ResultProperty); } set { SetValue(ResultProperty, value); } } public static readonly DependencyProperty ResultProperty = DependencyProperty.Register("Result", typeof(string), typeof(MyViewModel), new UIPropertyMetadata(string.Empty)); public void Search(string search_clause) { Result = string.Empty; SearchClause = search_clause; var worker = new BackgroundWorker(); worker.DoWork += worker_DoWork; worker.RunWorkerCompleted += worker_RunWorkerCompleted; IsBusy = true; worker.RunWorkerAsync(); } void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { IsBusy=false; Result = "Sorry, no results found for: " + SearchClause; } void worker_DoWork(object sender, DoWorkEventArgs e) { Thread.Sleep(5000); } } }
Hope this helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With