3

After looking at some of the MVVM toolkits(MVVM Light, SimpleMVVM) out there the common theme seems to try to use as many blendable events as possible and not use codebehind.

I am not sure how to do all the events. For instance 2 events come to bind when doing windows phone 7.

  1. OnNavigatedTo/From
  2. On Load

Does anyone have examples on how to do this in MVVM? I am using SimpleMVVM but I would hope that the examples might be similar and maybe MVVM light toolkit or even just general MVVM tutorial showing this might help.

I only found ones that show how to do like the button click.

Edit

I am sort of confused on when to use code behind events or use blend events to commands.

For instance in the the MVVM Light tutorials they use MVVM for navigation but why is that better than using a codebehind event?

I am also kinda confused now when people say

Codebehind isn't evil; its the mix of business logic and codebehind that is problematic. Let your UI handle UI tasks in your codebehind.

Well in the MVVM light examples they have "isbusy" in one of the examples where when the list or whatever it was(forgot) is loading a "loading sign comes up". This was all done in ViewModel and not a codebehind event.

So this seems kinda conflicting to me(maybe I am missing something). What also puzzles me is that if the ViewModel does not know anything about loading how do you know when the loading has started or finished?

AxelEckenberger
  • 16,628
  • 3
  • 48
  • 70
chobo2
  • 83,322
  • 195
  • 530
  • 832
  • What about EventToCommand? Both Blend SDK and MVVM Light provide an implementation of this. – Federico Berasategui Feb 18 '13 at 18:15
  • Ya was thinking of that but still would not know how to use it. I was also reading this article. http://blog.tonysneed.com/2011/07/22/commands-versus-event-triggers-in-mvvm/ – chobo2 Feb 18 '13 at 18:23
  • can you use System.Windows.Interactivity with Windows-phone-7? – A Aiston Feb 18 '13 at 18:47
  • 1
    Codebehind isn't evil; its the mix of business logic and codebehind that is problematic. Let your UI handle UI tasks in your codebehind. Your viewmodels shouldn't really know when you're navigating, or when your UI element is loaded. –  Feb 18 '13 at 19:01
  • Can you explain in a bit more detail "viewmodels shouldn't really know when you're navigating". I thought people do navigating through MVVM. I know codebehind is not evil but it seems like 1st choice is not to use it though as it makes test and such easier. – chobo2 Feb 18 '13 at 22:06

2 Answers2

2

As HighCore commented, use EventToCommand. It's pretty simple to use, although you'll need the Blend SDK first.

...
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.SL4"
xmlns:im="clr-namespace:Microsoft.Expression.Interactivity.Media;assembly=Microsoft.Expression.Interactions"
xmlns:ic="clr-namespace:Microsoft.Expression.Interactivity.Core;assembly=Microsoft.Expression.Interactions"
...
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
            <cmd:EventToCommand Command="{Binding GetTweetsCommand}" CommandParameter="Twitter" />
        </i:EventTrigger>
</i:Interaction.Triggers>

Also, just a general point on the code-behind: having UI-related functionality in the code-behind isn't the worst thing in the world! It's separate from your ViewModel and it's in a logical place. However, I find behaviours easier to test. For example, using a class inheriting from TargetedTriggerAction allows a storyboard to be controlled by both property changes and controls:

public class ImageAnimationTrigger : TargetedTriggerAction<Storyboard>
{
    protected override void Invoke(object parameter)
    {
        if (Target == null)
            return;

        if (parameter is DependencyPropertyChangedEventArgs)
        {
            DependencyPropertyChangedEventArgs args = (DependencyPropertyChangedEventArgs)parameter;

            if ((bool)args.NewValue)
                Target.Begin();
            else
                Target.Stop();
        }
        else if (parameter is RoutedEventArgs)
        {
            RoutedEventArgs args = (RoutedEventArgs)parameter;

            if (!(args.OriginalSource as Button).IsEnabled)
                Target.Begin();
            else
                Target.Stop();
        }
    }
}

I use this behaviour with a PropertyChangedTrigger as follows:

<i:Interaction.Triggers>
    <ic:PropertyChangedTrigger Binding="{Binding Loading}">
        <behav:ImageAnimationTrigger TargetName="animStoryboard" />
    </ic:PropertyChangedTrigger>
</i:Interaction.Triggers>

As Laurent Bugnion says, use the code-behind if you need to!

James Wright
  • 3,000
  • 1
  • 18
  • 27
  • I will try that out and see how it works. I like blend so that is not a problem! Is there any guidelines to use code behind vs eventToCommands. Like what I gathered it seems like it is better to do eventToCommands but I only seen click done. With you loaded can I see the code it is hooked up to not sure about "CommandParameter="Twitter" " – chobo2 Feb 18 '13 at 22:10
  • Most of the developers I've spoken to on the subject said that there are no fast and hard rules on how things should be set out, as long as the pattern is followed. My use of behaviours is down to a personal preference. Sorry for the lack of clarity about the command being called. I am using the `RelayCommand` class provided by MVVM Light, which implements the ICommand interface. This command points to a method called GetTweets, taking a string as a parameter to query Twitter's search API. 'Twitter' is just a query I specified. – James Wright Feb 18 '13 at 22:23
  • If it helps, the full code can be found [here](https://github.com/jamesseanwright/silvertweet). It's just a little something I made during a spike at work. – James Wright Feb 18 '13 at 22:26
  • It does not compile for me "The name "BooleanToVisibilityConverter" does not exist in the namespace "clr-namespace:SilverTweetMVVM.Converters"., "Cannot find all types required by the 'async' modifier. Are you targeting the wrong framework version, or missing a reference to an assembly?" – chobo2 Feb 18 '13 at 23:17
  • Hmmm that's odd. Sorry about that, I'll look into it today. – James Wright Feb 19 '13 at 07:38
  • I can't really try anything out on my machine at work since I installed the Xbox ADK, as it overwrites certain libraries required for standard Silverlight development. All I can think of is that you either cloned the MVVM branch instead of the master branch. Sorry I couldn't be of more help, I have compiled this project on two machines with no problems. – James Wright Feb 19 '13 at 09:18
  • Oh I will try and see if I can figure it out. Some things popped out at me though. I see you have no locator class. I though that was required. – chobo2 Feb 19 '13 at 17:11
  • Regarding the comment about "no fast and hard rules on how things should be set out, as long as the pattern is followed." what are the main points of the pattern being followed. I thought one was testability and hence why codebehind is not the ideal choice. – chobo2 Feb 19 '13 at 17:55
  • I didn't use a ViewModelLocator class because there's only one ViewModel, hence I didn't see the point. However, the AppFog WP7 project on my GitHub account uses one. Even if you used the code-behind, you could still test your other levels of logic, plus the code-behind itself. I've never had luck with that approach as I found referencing the view dependencies unreliable e.g. WP7 assemblies don't really work in a Silverlight Unit Test project. This is just what I've been told by a developer, but I found behaviours to be more testable, so I generally agree with you. – James Wright Feb 19 '13 at 18:55
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/24780/discussion-between-james-wright-and-chobo2) – James Wright Feb 19 '13 at 18:58
  • I have my own rule of thumb for code-behind vs. EventCommands/ViewModel : imagine if you needed to create an entirely new UI for your application - it's for a blind person. They wouldn't need loading icons, page animations, or modal dialogs - but they'd still need to know that something is loading or that there's a conflict between two business objects that they need to resolve. – Kyle Hale Feb 27 '13 at 15:32
0

1) Unfortunately I didn't find good examples so you are on your own.

2) if you keep your code-behind blank (by using commands instead of button click) you concentrate your code in ViewModel only. I can see two points of benefits:

a) in case you use one ViewModel for different Views (and have some common commands in several vies),

b) in case you use some private variables/methods of your ViewModel which are not available in the View.

3) You may use RaisePropertyChanged to load (reload) data, load data in ViewModel constructor to avoid using OnNavigatedTo or something else.

QArea
  • 4,955
  • 1
  • 12
  • 22