WPF Data Triggers and Story Boards


I'm trying to trigger a progress animation when ever the ViewModel/Presentation Model is Busy. I have a IsBusy Property, and the ViewModel is set as the DataContext of the UserControl. What is the best way to trigger a "progressAnimation" story board when the IsBusy property is true? Blend only let med add Event-Triggers on a 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 target name is obvisouly NOT what I want.

I was hoping to solve this in XAML using data binding techniques, in stead of having to expose events and start/stop the animation through code.

Best Answer

What you want is possible by declaring the animation on the progressWheel itself: The XAML:

<UserControl x:Class="TriggerSpike.UserControl1"
Height="300" Width="300">
    <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"/>
    <TextBlock Name="progressWheel" TextAlignment="Center" Opacity="0">
                    <DataTrigger Binding="{Binding IsBusy}" Value="True">
                                    <StaticResource ResourceKey="SearchAnimation"/>
                                   <StaticResource ResourceKey="StopSearchAnimation"/> 
    <Label Content="Here your search query"/>
    <TextBox Text="{Binding SearchClause}"/>
    <Button Click="Button_Click">Search!</Button>
    <TextBlock Text="{Binding Result}"/>

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;

        private void Button_Click(object sender, RoutedEventArgs e)

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;

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            Result = "Sorry, no results found for: " + SearchClause;

        void worker_DoWork(object sender, DoWorkEventArgs e)

Hope this helps!

Related Topic