Saturday, April 27, 2013

MVVM Design Pattern in Silverlight


MVVM in Silverlight is an interesting concept. Please read few articles related to MVVM before implementing the techniques described here.

After reading several contents related to MVVM in Silverlight, I came to the following conclusions.
1. MVVM allows the View (UI) to be separated from the Data and the Logic.
2. MVVM implementation will completely remove all the code in the code-behind xaml.cs file.
Here are some implementation techniques.

Let’s assume that the UI contains a dropdown list. This list needs to be populated and whenever the user makes a selection the application needs to know what the user has selected.

Here is the XAML code.

<ComboBox x:Name="comboBoxStateCode" ItemsSource="{Binding StateCodes}"   Grid.Row="0" Grid.Column="1"  HorizontalAlignment="Left" Width="110" Height="20" />
The ItemsSource is bound with the property "StateCodes". This "StateCodes" property belongs to the View Model class. It is declared like this in the View Model

Here is the code in the .cs file of the View Model.

     private ICollectionView stateCodes;
        public ICollectionView StateCodes
        {
            get
            {
                return stateCodes;
            }
            set
            {
                stateCodes = value;
                RaisePropertyChanged("StateCodes");
            }
        }

Here we are using "ICollectionView" and we are also raising the "Property Changed Event". There is a reason behind these two.


 List<string> availablestateCodes = someFunctiontogetData() as List<string>;
 StateCodes = new PagedCollectionView(availablestateCodes);
 stateCodes.CurrentChanged +=new EventHandler(stateCodes_CurrentChanged);

Reason 1.

This helps to trigger an event whenever the user makes a selection from the dropdown list.

stateCodes.CurrentChanged - This is an Event Handler.

void stateCodes_CurrentChanged(object sender, EventArgs e)
{
string userSelectedStateCode = stateCodes.CurrentItem as string;
UserMessage = "User selected State : " + userSelectedStateCode ;
}

Reason 2.

The following call makes sure that the property (remember the public property not the private variable) changed event call is triggered. This trigger ensures that whenever the property value is changed the values are reflected back in the UI.


RaisePropertyChanged("StateCodes");

Make sure that the View Model class is derived from INotifyPropertyChanged

public class myVMClass : INotifyPropertyChanged

Here is the Property Changed Event.

public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyname)
      {
            if (PropertyChanged != null)
            {
   PropertyChanged(this, new PropertyChangedEventArgs(propertyname));
            }
        }

Also make sure the XAML file has been linked to the View Model class like this.

    <UserControl.DataContext>
        <viewModels:myVMClass></viewModels:myVMClass>
    </UserControl.DataContext>

Now let us look into a button click operation. Remember there will not be any code in the code-behind file because of the button click action. This is how the button click event is wired up.

<Button x:Name="buttonTest" Grid.Row="1" Grid.Column="2" Width="100" Height="25" Content="Perform Test" Command="{Binding PerformTests}" />

The Command is bound with a property called 'PerformTests'.

        private RelayCommand<object> performTests;
        public ICommand PerformTests
        {
            get
            {
                return performTests;
            }
        }

The private variable 'performTests' is initialized like this.

performTests = new RelayCommand<object>(SubmitTest, CanSubmitTest);

This is the RelayCommand class implementation.


public class RelayCommand<T>  : ICommand
    {
        readonly Predicate<object> canExecute;
        readonly Action<object> executeAction;
        public RelayCommand(Action<T> execute)
        {
        }

public RelayCommand(Action<object> inExecuteAction, Predicate<object> inCanExecute)
        {
            if (inExecuteAction == null)
            {
MessageBox.Show("inExecuteAction is null.", "Error", MessageBoxButton.OK);
                return;
            }
            executeAction = inExecuteAction;
            canExecute = inCanExecute;
        }

        bool ICommand.CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            executeAction(parameter);
        }

        event EventHandler ICommand.CanExecuteChanged
        {
            add { }
            remove { }
        }
    }

This is the 'CanSubmitTest' and 'SubmitTest' function implementation.

        public bool CanSubmitTest(object obj)
        {
            return true;
        }
        public void SubmitTest(object obj)
        {
            CallAnyFunctionforButtonClickAction();
        }

In the function 'SubmitTest' call the button click action function.

Hope this article gives a basic idea of the MVVM implementation. I will try to cover the MVVM AutoComplete box implementation in my next post.

Happy coding.

Cheers
Anand




 

All Blogs so far ...