locked
Make start a storyboard on a event from ViewModel (MVVM) RRS feed

  • Question

  • I have a storyboard that should start anytime a certain event - from another object - is called.

    So far, I solved using a trick like this

    <DataTrigger Binding="{Binding IsUpdating}" Value="True">
    	<DataTrigger.EnterActions>
    		<BeginStoryboard>
    			<Storyboard>
    				 ...
    			</Storyboard>
    		</BeginStoryboard>
    	</DataTrigger.EnterActions>
    </DataTrigger>

    When the event on my ViewModel is fired, I use this trick:

    // event fired
    
    App.Current.Dispatcher.BeginInvoke((Action)delegate()
    {
    	IsUpdating = false;
    	IsUpdating = true;
    });


    Sure this code works, but this is not a very elegant way.

    Any better solution to make the storyboard begin from the event ?



    • Edited by F Starred Friday, March 8, 2013 4:38 PM
    Friday, March 8, 2013 4:37 PM

Answers

  • These are the elemens for eventing w/o 'piggybacking' the Binding mechanism.

    The concept is that there are as many events as there are interaction 'types' between the XAML layer and the VM layer. Typically an interaction 'type' is an Action Event with possibly an Enum as argument to refine [on 'switch'] the wanted action within the XAML widget. Hereafter, I used a string arg.

    - ViewModel

        public interface IEventingViewModel
        {
            // Declares part of View Model for non-binding events
            // e.g. for "action" in XAML layer
            // Examples
            event Action Sto1Evnt;
            event Action<string> Sto2Evnt;
        }
        public class ViewModel : IEventingViewModel
        {
            public event Action Sto1Evnt;
            private void OnSto1Evnt()
            {
                if (Sto1Evnt != null)
                    Sto1Evnt();
            }
            public event Action<string> Sto2Evnt;
            private void OnSto2Evnt(string s)
            {
                if (Sto2Evnt != null)
                    Sto2Evnt(s);
            }
        }
    
     

    - XAML Widget:

            {
                this.DataContextChanged += DataContextChangedEvent;
            }
    
            void DataContextChangedEvent(object sender, DependencyPropertyChangedEventArgs e)
            {
                // Cast Data Context to IEventingViewModel
                // (Un)Listen on wanted Event(s) 
                // [watch out for memory leaks, hence unlisten first if previous DC not null]
                // Execute Storyboard, pulled from XAML code 
                // or defined in code-behind
            }
    

    • Marked as answer by F Starred Monday, March 18, 2013 3:19 PM
    Saturday, March 16, 2013 9:29 AM

All replies

  • Hi F Starred,

    Try to use EventTrigger, it applies a set of actions in response to an event, included  animations.

    Since the event is your customer event, you can firstly customer it as routed event, more information please refer to:http://msdn.microsoft.com/en-us/library/ms752288.aspx

    And then use use these code below to start the stroyboar.

    <Style>
    <Style.Trigger>
       <EventTrigger RoutedEvent="{x:Static local:Yourclass.yourEvent}">
             <BeginStoryboard>
                     .........
             </BeginStoryboard>
        </EventTrigger>
    </Style.Trigger>
    </Style>
    Regards,

    Lisa Zhu [MSFT]
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, March 12, 2013 7:22 AM
  • Thank you for the answer. The only problem is the event belongs from my viewmodel and cannot be static. Moreover, a routed event can not be binded

    Tuesday, March 12, 2013 1:29 PM
  • Anyone can help me please ?
    • Edited by F Starred Friday, March 15, 2013 10:38 AM
    Friday, March 15, 2013 10:36 AM
  • These are 2 other ideas [don't say they are necessarily better]:

    - Binding to DependencyProperty of type int and executing StoryBoard(*) in its Callback upon +1 from ViewModel bound property
    - declaring an Event [with Args if required] in ViewModel and (un)listening it upon DataContext change. Perform StoryBoard(*) in listener. This one is probably the 'cleanest', conceptually.

    (*) for simplicity, Storyboard declared in XAML

    Friday, March 15, 2013 11:37 AM
  • These are 2 other ideas [don't say they are necessarily better]:

    - Binding to DependencyProperty of type int and executing StoryBoard(*) in its Callback upon +1 from ViewModel bound property
    - declaring an Event [with Args if required] in ViewModel and (un)listening it upon DataContext change. Perform StoryBoard(*) in listener. This one is probably the 'cleanest', conceptually.

    (*) for simplicity, Storyboard declared in XAML

    About the second concept, that sounds good to me, can you give me please - if you can - just a few line of what the event in ViewModel should be declared and called?

    I'm not sure if I have completely figured out .

    Thank you !

    Friday, March 15, 2013 2:31 PM
  • These are the elemens for eventing w/o 'piggybacking' the Binding mechanism.

    The concept is that there are as many events as there are interaction 'types' between the XAML layer and the VM layer. Typically an interaction 'type' is an Action Event with possibly an Enum as argument to refine [on 'switch'] the wanted action within the XAML widget. Hereafter, I used a string arg.

    - ViewModel

        public interface IEventingViewModel
        {
            // Declares part of View Model for non-binding events
            // e.g. for "action" in XAML layer
            // Examples
            event Action Sto1Evnt;
            event Action<string> Sto2Evnt;
        }
        public class ViewModel : IEventingViewModel
        {
            public event Action Sto1Evnt;
            private void OnSto1Evnt()
            {
                if (Sto1Evnt != null)
                    Sto1Evnt();
            }
            public event Action<string> Sto2Evnt;
            private void OnSto2Evnt(string s)
            {
                if (Sto2Evnt != null)
                    Sto2Evnt(s);
            }
        }
    
     

    - XAML Widget:

            {
                this.DataContextChanged += DataContextChangedEvent;
            }
    
            void DataContextChangedEvent(object sender, DependencyPropertyChangedEventArgs e)
            {
                // Cast Data Context to IEventingViewModel
                // (Un)Listen on wanted Event(s) 
                // [watch out for memory leaks, hence unlisten first if previous DC not null]
                // Execute Storyboard, pulled from XAML code 
                // or defined in code-behind
            }
    

    • Marked as answer by F Starred Monday, March 18, 2013 3:19 PM
    Saturday, March 16, 2013 9:29 AM
  • Yes it works! Although is a pity that I must write some code-behind, is an enough elegant solution.

    Thank you

    Monday, March 18, 2013 3:19 PM