Showing posts with label MVVM. Show all posts
Showing posts with label MVVM. Show all posts

January 21, 2015

MVVM/MVC/MVP Explained

There is a nice explanation here

The represent several ways to manage and coordinate the GUI but the important thing is that the model is always segregated from the GUI. Usually the model is described as some database classes but the Model can contain threads and timers and event publishers so this overly simplistic view does not do it any justice. I prefer to view the model as an API on the business logic. A good way to create a model is using test classes from a test framework (such as NUnit or MS-Test). Using a GUI framework is a dangerous approach because it encourages the use of GUI objects within the model, even a simple message dialog within some model code can throw a spanner in the works so to speak.

The View represents the UI components such as CSS, jQuery, html, WinForms, WPF, Silverlight, XAML

February 18, 2014

Routing Events to Commands in WPF using MVVM Light

First reference some assemblies:
  • System.Windows.Interactivity
  • GalaSoft.MvvmLight.Extras.WPF4
In the XAML file add references to the namespaces in the window definition:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
Within you window component, add the event to command handler's
<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=LoadedCommand}"
                        PassEventArgsToCommand="True" />
    </i:EventTrigger>
    <i:EventTrigger EventName="Closing">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=ClosingCommand}"
                        PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>
Then some code to process the command:
private RelayCommand<RoutedEventArgs> loadedCmd;

public RelayCommand<RoutedEventArgs> LoadedCommand
{
  get
  {
    return this.loadedCmd ?? (this.loadedCmd = new RelayCommand<RoutedEventArgs>
    ((rea) => 
    {
      // Use event argument 'rea' if you need it 
      // (but PassEventArgsToCommand="True" is needed in the Xaml, see above)
      this.ActivityText = "Copy files from \'" +
         m_AsyncPhotoBackup.TargetDirectory +
         "\' to \'" +
         m_AsyncPhotoBackup.DestinationDirectory +
         "\'.";
      m_AsyncPhotoBackup.RunWorkerAsync();
    }));
  }
}

TaskbarItemInfo in MVVM and Sample WPF Converter Usage

In this case we are using a WPF TaskbarItemInfo to show progress on an icon in the Taskbar. The taskbar progress value takes a double value between 0.0d and 1.0d. However, in this cae the progresss value is generated as an integer percentage between 0 and 100. So we create a converter class to convert our interger value between 0 and 100 to the double value. An alternative would be to create another property that creates the progress value in the appropriate form.
// Convert an integer percentage (0 to 100) to a double 
// between (0.0d and 1.0d)
public class IntPercentageToDoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        double res = 0.0d;
        if (value is int)
        {
            int intVal = (int)value;
            res = intVal / 100.0d;
            if (res < 0.0d)
                res = 0.0d;
            else if (res > 100.0d)
                res = 100.0d;
        }
        return res;            
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, CultureInfo culture)
    {
        return null;
    }
}
In the Xaml we first need to create an instance of the converter. A few namespace declarations are required:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PhotoBackupApp.ViewModel"
Create the converter instance:
<Window.Resources>
    <local:IntPercentageToDoubleConverter x:Key="intPercentageToDoubleConverter" />
</Window.Resources>
Use the converter with the bound proprety
<Window.TaskbarItemInfo>
    <TaskbarItemInfo ProgressValue="{Binding Mode=OneWay, 
       Path=ProgressPercentage, 
       Converter={StaticResource intPercentageToDoubleConverter},
       UpdateSourceTrigger=PropertyChanged}" 
       ProgressState="Normal" />
</Window.TaskbarItemInfo>
The 2 important declarartions here are 'Path=ProgressPercentage, Converter={StaticResource intPercentageToDoubleConverter},'. This is the property to bind to and the converter instance to use.

Closing a Dialog Window in WPF using MVVM

Alot of ideas are mentioned on this website:
http://stackoverflow.com/questions/4376475/wpf-mvvm-how-to-close-a-window

Simplest way is to simply define the close button as normal using the click event
<Button Content="OK" IsDefault="True" Click="okButton_Click" />
Here is the code behind:
private void okButton_Click(object sender, RoutedEventArgs e)
{
 this.Close();
}
This does not affect the ViewModel in any way, the ViewModel knows nothing about the close functionality. and there is nothing wrong with code behind if it does not affect the ViewModel.
However I wanted to be able to initiate the Close from the ViewModel. To do this I defined a property that takes a simple Action delegate
public Action CloseAction { get; set; }
In the constructor I give it a default value
this.CloseAction = () => 
    { Debug.WriteLine("ActivePhotoBackupViewModel - Close Action Undefined"); )};
Now I can use a command to perform the CloseAction
#region Done Command
private RelayCommand doneCommand;

public RelayCommand DoneCommand
{
 get
 {
  return this.doneCommand ?? 
    (this.doneCommand = new RelayCommand(() => 
     {
      DoSomeOtherStuffHere();
      this.CloseAction();
     }
    ));
 }
}
#endregion Done Command
When creating the view model the close action is defined:
...
ActivePhotoBackupViewModel vm = new ActivePhotoBackupViewModel(srcDir, destDir, photoBackupOptions);
PhotoBackupDlg photoBackupDlg = new PhotoBackupDlg();
vm.CloseAction = new Action(() => photoBackupDlg.Close());
...
Could have a used an interface here on a class to perform the same work but then the interface would have had one method so it is simpler just to use a delegate instead ('Action' is a system defined delegate). Also there were no future extra requirements envisaged on this interface (otherwise the interface route would have been worth it). This simple solution does not impede any unit testing of the ViewModel either.

March 28, 2012

WPF/Silverlight MVVM

Quick Intro to MVVM A small introduction

Getting Started with the MVVM Pattern in Silverlight Applications

MVVM Light Toolkit
Download it here - There is a couple of videos here as well!

Chapter 5: Implementing the MVVM Pattern
Chapter 6: Advanced MVVM Scenarios - Most introductions only explain the topic in a basic way which does not occur in reality. Here, they show how to deal with the tricksey areas

Simplifying commands in MVVM and WPF - I like the adapted approach proffered by David N. in the comments

Using the BackgroundWorker in a Silverlight MVVM Application - Most of my apps have background worker threads or threading in some manner.

WPF MVVM Commands - new reduced-boilerplate recipe - Not so keen on this approach