MVVM- Trigger Storyboard in the View Model in Silverlight - silverlight

I have a couple of Storyboards in my view that I would like to trigger from the ViewModel if possible. Is there a simple way or elegant way of doing this. Here is what I am trying to do.
Person Clicks on a Button-->RelayCommand (In the ViewModel), the Relay Command should then play the storyboard. Also one more thing, I would like to also trigger the storyboard animation by itself in the ViewModel without any interaction.
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<cmd:EventToCommand Command="{Binding ButtonPress}" CommandParameterValue="RedButtonLight">
</cmd:EventToCommand>
</i:EventTrigger>
</i:Interaction.Triggers>

I know it's a long time ago. But I've written a detailed blog post about Triggering Storyboards and MVVM.
http://mark.mymonster.nl/2010/12/14/trigger-a-storyboard-on-viewmodel-changes/

If the button click is purely to power a view-related thing and isn't doing any actual application logic, then I would argue that you can do all this in the code-behind of the view class.
If this isn't the case then I would use a property on the Presentation (ViewModel) to signal that the Presentation is in a state, and have the view react to the PropertyChanged event and start the storyboard. This is assuming you are implimenting INotifyPropertyChanged on your Presentation class.

Have a look at the expression samples. There is a trigger for events from the datacontext. DataEventTrigger
You could use that to trigger a ControlStoryboardAction to start the story board whenever your viewmodel raises a particular event.
Your viewmodel could then raise the event as part of the command as well as at other times.

Heres how you can do it in blend without touching a line of xaml or code :
http://www.basarat.com/2011/05/expression-blend-starting-storyboard.html

Related

WPF EventTrigger for SourceInitialized

in my window I want to use this code
<i:Interaction.Triggers>
<i:EventTrigger EventName="SourceInitialized">
<command:EventToCommand Command="{x:Static wpf:Window.InitializeWindowProcessHookCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
to hook the SourceInitialized event to a command on my so-called Window class.
I am using MvvMLight EventToCommand and if it works perfectly if I use the Loaded event instead of the SourceInitialized, so we can assume that the command and further logic is working.
Additionally, using the event with code behind works, but I am looking for a solution using EventTriggers (if possible).
When looking up a possible solution, I stumbled across a topic on MSDN, which is about this exact topic, and the OP points states that he successfully bound to the Loaded event, but cannot get binding to the SourceInitialized to work
[and I] want to write a similar one for windows source initialized event,  but find that Window.SourceInitializedEvent is not exposed
Is there any possible solution to that?
Many thanks in regard
The SourceInitialized event fires before your trigger has a chance to invoke the command so this won't work.
Also, it doesn't make much sense to fire the command using an EventTrigger that is defined in the XAML markup just for the sake of not having to do it from the code-behind of the same view. MVVM is not about eliminating view-related code from the views and it doesn't break the pattern to invoke the command from the code-behind of the same view as your XAML markup is defined in.
So invoke the command from an event handler in the code-behind or subscribe to another event.
As you have already noticed, there is no way to handle the SourceInitialized event of a window using an EventTrigger that is defined in the XAML markup of the same window.

ViewModel Handling Events

I saw an question here where OP asked about binding events to ViewModel. Basically ViewModel shall respresent an abstract View containing necessary data from Model so that the View may be also able to use Bindings. But to be able to fullfill all that the ViewModel must also conver most of the use cases which are happening in the View such as example if search textbox is empty the search button shall be greyed out. That works fine but lets add events to the game. It would be way easier if Button.Click where bindable to an EventHandler in ViewModel and inside the event handler you would be then able to use model objects.
Now my question is since WPF supports event driven programming why cant events be handled in ViewModel? How could I provide binding events funcionality?
Event handlers would sit in the view's code behind file. If you're using MVVM, then you'll want to minimise the amount of code in a code behind file.
WPF supports commanding, and the ICommand interface includes a CanExecute and Execute method. There are implementations of ICommand which allow these methods to be implemented on the view model.
Having said that, commanding also has its limitations, so you should consider using an MVVM framework when using MVVM. Something like Caliburn.Micro comes with Actions which also allow verbs on the view model to be invoked based on control events.
It is because the use of event explicitly breaks the MVVM pattern (as I am sure you are aware). However there is another way around this - by using the Attached Command Behaviour pattern. More information here.
Code for a small but great framework for attached commands is downloadable from here.
I hope this helps.
Edit. attached behaviour allow you to use events without breaking the MVVM pattern. The use is like
<Border Background="Yellow" Width="350" Margin="0,0,10,0" Height="35" CornerRadius="2" x:Name="test">
<local:CommandBehaviorCollection.Behaviors>
<local:BehaviorBinding Event="MouseLeftButtonDown"
Action="{Binding DoSomething}"
CommandParameter="An Action on MouseLeftButtonDown"/>
<local:BehaviorBinding Event="MouseRightButtonDown"
Command="{Binding SomeCommand}"
CommandParameter="A Command on MouseRightButtonDown"/>
</local:CommandBehaviorCollection.Behaviors>
<TextBlock Text="MouseDown on this border to execute the command"/>
</Border>

MVVM restricts Code Behind?

Does using MVVM model in WPF restricts the programmer from writing code behind? Avoiding Code behind results in lot of complications but on the other hand coupling rises as an issue. So what is better?
The MVVM model does NOT restrict you from writing code behind.
What it does promote is that the View should only be dependent on the ViewModel (and the ViewModel on the Model)
So if you write code behind that is actually implementing the ViewModel you are creating a dependency from the ViewModel to the View.
Code behind that ONLY does View related things is OK
The thing you are losing when using code behind is the easy (unit)testing of that code.
EDIT
A common expression in MVVM-world is "XAML only". As much as I like a short, snappy statement it tends to divert from the actual problem MVVM is trying to solve and how it tries to solve it.
As long as you stick to making the View dependent on the ViewModel and the ViewModel on the Model AND strive for (unit)testability you are on the right track.
EDIT 2
In the View handling an event should only do two things: change the View itself or notify the ViewModel using a binding that something has changed. Notifying the VIEW of a change in the ViewModel should be done by implementing INotifyPropertyChanged on the ViewModel.
In a similar way the ViewModel can respond to events in the View by binding ViewModel Commands to the View.
A WPF Button has a Command property that can be used. It is executed when the button is clicked.
If a control has no Command property or you want to execute a command when a different event is raised all you have to do is turn the event into the execution of an ICommand.
Microsoft already provided an implementation of that in the Blend SDK. From this article:
... xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity..."
<Slider
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<i:InvokeCommandAction Command="{Binding MyCommand}"
CommandParameter="{Binding Text, ElementName=textBox}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Slider>
And a discussion about commands versus event triggers

How to assign RelayCommand to Click or SelectedIndexChanges events?

I'm just starting with MVVM light, but so far it allowed me to solve some of my issues. Infortunately I'm struggling with relatively sime issues in Silverlight.
Let's assume the following button with EventToCommand:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding UpdateAccountsCommand, Mode=OneWay}" CommandParameter="{Binding SelectedIndex, ElementName=lstLedgers}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
How to assign this code to SelectedIndexChanged event?
Futher issue - how to assign a command in C# code? The problem is as follows: I'm developing Windows Phone 7 app. Application Bar needs to be initiated in C# (as far as I know there is no xaml code for application bar at this stage). As a result I have no idea how to bind a command to a application bat button in from c#, now xaml.
Thanks in advance your your help.
How to assign this code to SelectedIndexChanged event
The event name is in the trigger's initial xaml line. The EventName is what triggers something to happen. You'll need to make sure that you have this trigger on an object with a SelectedIndexChanged event. Button doesn't have that event.
...
<i:EventTrigger EventName="SelectedIndexChanged">
...
If you are breaking mvvm for the application bar, I don't know why you'd want to create a trigger. You might as well go the direct route by accessing the events you want directly. You can do it, don't get me wrong... just this code is a lot cleaner:
ApplicationBarButton.Click += new RoutedEventHandler(OnApplicationBarButton_Click);

MVVM What is the way of updating a UI after a command?

I'm learning MVVM through a project and I got stuck on something simple.
I have a Button that updates a ListView. I have a command in the ViewModel that make the right things but I want to select the new row and get the focus on a TextBox after I click the Button.
The question is: How do I update my UI after executing a command?
If I need to change my windows Title when an operation have been made, I use a property on the ViewModel that is binded to the Window's title and it's changed when I need it but, I don't know how to get focus on a control when a command has been executed.
Thank you.
To select the new row, add a new property to your ViewModel ("SelectedItem" for instance), and bind the ListView's SelectedItem property to it :
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">...
In the ViewModel, you just have to assign the new item to the SelectedItem property
To focus the TextBox, Mike's idea seems a good one
You could make an attached behavior. I'd suggest using the new Blend behavior framework, ie TriggerAction that contained this custom logic.
For your attached behavior you put on the button, give it a DP for an ICommand and maybe a DP of a ListView type.
On the "protected override void Invoke(object parameter)" of your TriggerAction, execute your ICommand, then you have reference to your ListView. Here you can do your custom code on it, like setting focus.
Your XAML may look something like this:
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Behaviors:CustomBehavior Command="CommandName" ListView="{Binding ElementName=myListView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button/>
I suggest looking at Mike Brown's ExecuteCommandAction behavior (download here), it's about almost 1/2 of what you need.
What about setting focus to the control in the code behind: textBox.Focus()
I consider everything you mention in your question to be GUI logic so I would add a Click event to the button to handle stuff that needs to happend in the GUI.
Hope this helps.
I think you need to use the Mediator pattern. Please see this:
Josh Smith's Mediator Prototype for WPF Apps
This is generally used in communicating with the View from the View-Model. Hope this helps.
In your case you need some way that the ViewModel notifies the View that it should set the focus on a specific control.
This could be done with an IView interface. The view implements this interface and the ViewModel can call a method of the View over this interface. This way you have still the View and ViewModel decoupled of each other.
How this can be done is shown here:
WPF Application Framework (WAF)
http://waf.codeplex.com

Resources