none
MVVM ultra easy example for beginners

    General discussion

  • A lot of MVVM articles confound a newbie to MVVM.  This example is the most basic (without commanding) example one could find.  In fact, you can put all of this code in the code behind of the View's file in the same namespace.  Not the best thing to do, but it leads to a crystal clear understanding of MVVM:

    Create a project named EasyMVVM, paste this code into view.

    <Window x:Class="EasyMVVM.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:vm="clr-namespace:EasyMVVM"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.Resources>
                <vm:MainWindowVM x:Key="vm"></vm:MainWindowVM>
            </Grid.Resources>
            <ListBox ItemsSource="{Binding Source={StaticResource vm}, Path=BoundProperty}"/>
        </Grid>
    </Window>

    Now double click on the MainWindow.cs file and paste in this code:

    using System;
    using System.Windows;
    using System.ComponentModel;
    using System.Collections.ObjectModel;
     
    namespace EasyMVVM
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
        //This is the Mainwindow's View Model which will be the datacontext in the xaml of the MainView
        public class MainWindowVM : DependencyObjectINotifyPropertyChanged {
     
            public MainWindowVM()
            {
                Model m = new Model();
                BoundProperty = m.GetData();
            }
     
            //set up a private class varialbe that holds the value of the _Backing Property
            private ObservableCollection<string> _BackingProperty;
            //This is the publically viewable Property for this class
            public ObservableCollection<string> BoundProperty
            {
                get { return _BackingProperty; }
                set { _BackingProperty = value;
                PropChanged("BoundProperty");
                }
             }
            //This event will be fired to notify any listeners of a change in a property value.
            public event PropertyChangedEventHandler PropertyChanged;
            //Tell WPF Binding that this property value has changed
            public void PropChanged(String propertyName)
            {
                //Did WPF registerd to listen to this event
                if (PropertyChanged != null)
                {
                    //Tell WPF that this property changed
                    PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
                }
            }
        }
        //The model is a class which the ViewModel knows and uses to get data...
        public class Model {
            //Using a private data store is a good idea
            private ObservableCollection<string> _data = new ObservableCollection<string>();
            public ObservableCollection<string> GetData()
            {
                //these steps represent the same data to be returned each time GetData is called.
                //typically you'd query a database or put other buisness logic here
                _data.Add("First Entry");
                _data.Add("Second Entry");
                _data.Add("Third Entry");
                return _data;
            }
        
        }
    }
    
    You are all set, this is the most simple fundamental MVVM pattern one can experience... It takes away weeks of obscure article reading for the NOVICE.

    JP
    Monday, July 18, 2011 9:05 PM

All replies

  • I must ask, why implement both the DependencyObject and INotifyPropertyChanged. :-)


    Developing is part of being a developer.
    Monday, July 18, 2011 9:27 PM
  • Habit more than anything, I usually use DependencyProperties with the DependecyObject providing me the GetValue and SetValue methods for them.  In this case because of the INPC the VM does not need to use the DependencyObject.  Plus I didn't show any DependencyProperty markup as well so you are right it doesn't need to be there.
    JP
    Tuesday, July 19, 2011 1:33 AM
  • ViewModels should never derive from DependencyObject.  Instead they should just implement the INotifyPropertyChanged interface.

    EDIT: You Model should also implement the INotifyPropertyChanged interface.  Also the Model is not used to get data, unless you are using an ActiveRecord pattern.  Repositories are used to get data.  The Model is the Object that you will bind your View elements to.  So you would have a property defined such as public Model MyModel {get... set...} in your ViewModel.


    Tuesday, July 19, 2011 2:39 AM
  • This is closer to what you would want to do:

      public class MainWindowVM : INotifyPropertyChanged
      {
        public MainWindowVM()
        {
          var repository = new ModelRepository();
          ModelProperty = repository.GetModel();
          ModelList = new ObservableCollection<Model>(repository.GetModels());
        }
    
        private Model _modelProperty;
        public Model ModelProperty
        {
          get { return _modelProperty; }
          set
          {
            _modelProperty = value;
            OnPropertyChanged("ModelProperty");
          }
        }
    
        private ObservableCollection<Model> _modelList;
        public ObservableCollection<Model> ModelList
        {
          get { return _modelList; }
          set
          {
            _modelList = value;
            OnPropertyChanged("ModelList");
          }
        }    
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String propertyName)
        {
          if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      }
    
      public class Model : INotifyPropertyChanged
      {
        private string _propertyName;
        public string PropertyName
        {
          get { return _propertyName; }
          set
          {
            _propertyName = value;
            OnPropertyChanged("PropertyName");
          }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(String propertyName)
        {
          if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
      }
    
      public class ModelRepository
      {
        public Model GetModel()
        {
          return new Model() { PropertyName = "First" };
        }
    
        public IList<Model> GetModels()
        {
          List<Model> models = new List<Model>();
          models.Add(new Model() { PropertyName = "First" });
          models.Add(new Model() { PropertyName = "Second" });
          models.Add(new Model() { PropertyName = "Third" });
          return models;
        }
      }
    

    Of course there is some room for refactoring, but this is just to illistrate the proper way to create your ViewModels.

    Tuesday, July 19, 2011 3:01 AM
  • Brain, the word "never" is absoute.  Please explain this strong adjective.  I'm not seeing any reasonable lurking catastrophy from a class that is one level below an Ojbect which everything in the system derives from anyway.  As I said, I favor DPs so using DOs give me those methods automatically.  That's the cheif reason I use them on view models. 

    I also haven't read too much on models implementation of INPC either.  Espeically in light of frameworks like EF 4.1.  or even WCF.  But I am open to your arugments.  To me I'm thinking models really pretty much just get the data and really don't (But can I guess) maintain the collections.  To me if the Model has the INPC then it's bluring the VM lines isn't it?  I've read nothing on Active Record patterns and nothing on Repositories.  In your example the additional logic adds nothing to the funtion of the current solution, if the data being served is the correct data.  But I do appreaciate the discussion with you!

    But then again I posted the example above for brand new MVVM users who like me in the beginning were whisked away of sub topics not related to MVVM.  The most fundamental thing to realize in MVVM is Binding and notification to WPF and then separation of the DataModel.  All the fancy stuff will then fall into place.

     


    JP
    Tuesday, July 19, 2011 3:31 AM
  • How would the XAML bindings change in your example Brian?
    JP
    Tuesday, July 19, 2011 3:32 AM
  • I normally don't speak in absolutes excpet in this case.  I will give you 3 technical reasons, not personal, why to never have a VM dervie from DO:

    1. DependencyObjects are not marked as Serializable
    2. DependencyObject overrides the Equals and GetHashCode methods
    3. A DependencyObject has thread affinity, meaning they can only be used on the thread which created them. So if your doing multi-threading you're out of luck.

    There are several other draw backs such as testing.  It is difficult to test a VM that derive from DO due to the need of a dispatcher.  Showing beginner to use DOs will set them up for major headaches down the road, plus promote a non standard approach of implementing a VM.  Also, it is standard for your client side model to implement the INotifyPropertyChanged ineterface along with other interfaces such as IDataErrorInfo.  If you look at EF 4.1 self yracking entities you will see they implement this interface.  WCF will not implement these interfaces because WCF is a messaging tehnology and you normally don't use the same DTOs for your models, but even if you did they should implement the interface.

    The Model should not know about the data store.  How a model is updated (CRUD) should be the responsibility of a repository.  A repository is simply a class that abstracts the functionality of CRUD operations away from the Model.  This provides clear separation of concerns and reinforces solid development techniques.  This also promotes an easily testable system.

    By the way, not everything in .NET derives from Object.

    Tuesday, July 19, 2011 3:49 AM
  • How would the XAML bindings change in your example Brian?
    JP


    I don't create the ViewModel in XAML, but if I did it may look something like this:

      <Window.DataContext>
        <local:MainWindowVM />
      </Window.DataContext>
    
      <Grid>
        <ListBox ItemsSource="{Binding ModelList}"/>
      </Grid>
    

    Tuesday, July 19, 2011 3:54 AM
  • Hi Acoustic,

     

    A dependency property is nice to have when you have following reasons-

    1) You want Value Inheritance in element tree.

    2) You want to rely upon multiple value providers.

    3) You want change notification to the UI.

    and

    A viewmodel is a kind of layer that does not participate in UI(Visual/Logical/Element tree) instead it provides a backend to hold the data that is expected to be shown by UI. Option 1 and 2 cannot be supported by VM(as no participation in UI).

    In this perspective there is single requirement- send notification to UI when some logic alters the data(held by VM) and to solve this purpose why to use a heavy derivation of DependencyObject while you can have a lighter option-INotifyPropertyChanged.

     

    Tuesday, July 19, 2011 4:13 AM
  • Hey Sanguine glad to see you lurking around here.

    Yes, agreed  with all your points above, but the question is when would one put a DPs into the Viewmodel as opposed to View?  They must be in the View if the control at hand wants to bind via xaml by a consumer of that control. 

    Agreed on your clarification on Viewmodel.  I call this the Datacontext of the View, or for new folks it is the "static" class of the view.  I say static because if one uses the XAML resource methods it becomes static.  You mention it's single requirement is send notification to GUI.  But it must receive new collection changes from Data side too.  I frequently use events to do this part.  Events in the Viewmodel such as UpdateDataInBoundStuff are used to send async. notifications by Model to tell VM when data is ready.  For a new person this is sufficient, because it is simple.


    JP
    Tuesday, July 19, 2011 10:35 AM
  • Brian;

    Points well taken.  Let me clairify by asking more questions if you don't mind.

    1) When would one be most concerned in Viewmodel serialization?

    2) Can these overrides you specify be overridden by inheritee?  When and how often are the Equals and GetHashCode methods utilized for ViewModels?

    3) Thread affinity question.  When would a viewmodel want to multithread?  Could the mutlithread logic be a new Task spin off?


    JP
    Tuesday, July 19, 2011 10:39 AM
  • Update to World's most easy MVVM sample 7/19/2011 (Removed refs. to Dependency Object) JP

    Step 1) Create new project named EasyMVVM, replace the XAML code and the CS code below in the XAML file named Mainwindow and it's code behind file named Mainwindow.cs

    <Window x:Class="EasyMVVM.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:vm="clr-namespace:EasyMVVM"
            Title="MainWindow" Height="350" Width="525">
        <Grid>
            <Grid.Resources>
                <vm:MainWindowVM x:Key="vm"></vm:MainWindowVM>
            </Grid.Resources>
            <ListBox ItemsSource="{Binding Source={StaticResource vm}, Path=BoundProperty}"/>
        </Grid>
    </Window>

    using System;
    using System.Windows;
    using System.ComponentModel;
    using System.Collections.ObjectModel;
     
    namespace EasyMVVM
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
        //This is the Mainwindow's View Model which will be the datacontext in the xaml of the MainView
        public class MainWindowVM :  INotifyPropertyChanged {
     
            public MainWindowVM()
            {
                Model m = new Model();
                BoundProperty = m.GetData();
            }
     
            //set up a private class varialbe that holds the value of the _Backing Property
            private ObservableCollection<string> _BackingProperty;
            //This is the publically viewable Property for this class
            public ObservableCollection<string> BoundProperty
            {
                get { return _BackingProperty; }
                set { _BackingProperty = value;
                PropChanged("BoundProperty");
                }
             }
            //This event will be fired to notify any listeners of a change in a property value.
            public event PropertyChangedEventHandler PropertyChanged;
            //Tell WPF Binding that this property value has changed
            public void PropChanged(String propertyName)
            {
                //Did WPF registerd to listen to this event
                if (PropertyChanged != null)
                {
                    //Tell WPF that this property changed
                    PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));
                }
            }
        }
        //The model is a class which the ViewModel knows and uses to get data...
        public class Model {
            //Using a private data store is a good idea
            private ObservableCollection<string> _data = new ObservableCollection<string>();
            public ObservableCollection<string> GetData()
            {
                //these steps represent the same data to be returned each time GetData is called.
                //typically you'd query a database or put other buisness logic here
                _data.Add("First Entry");
                _data.Add("Second Entry");
                _data.Add("Third Entry");
                return _data;
            }
        
        }
    }
    

    JP
    Tuesday, July 19, 2011 10:52 AM
  • Hey Acoustic, could you also update it in the initial thread ? It would help those who would enter the thread and not read it all. :-)

    And i would like to open a little debate regarding your setup, in this case, you set it up as a StaticResource, instead of using it as a DataContext, is there a particulare reason for this, or is it just the way you do ?

    I tend to do like this.

     

    <Window x:Class="EasyMVVM.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:vm="clr-namespace:EasyMVVM"
      Title="MainWindow" Height="350" Width="525">
    
      <Window.DataContext>
       <vm:MainWindowVM/>
      </Window.DataContext>
     <Grid>
      <ListBox ItemsSource="{Binding Source={StaticResource vm}, Path=BoundProperty}"/>
     </Grid>
    </Window>
    


     


    Developing is part of being a developer.
    Tuesday, July 19, 2011 11:19 AM
  • Interesting Acoustic.

     

    For an ObservableCollection you don't need INotifyPropertyChanged at all, it has inbuilt notification mechanism and at model class, you don't need Observable collection as this is backend stuff and not going to interact with view.

     

    what you say :)

     

    Tuesday, July 19, 2011 11:19 AM
  • I dunno what jp has to say but in a bigger real world situation you'd probably have some other properties as well as the model.

    These would of course need  the iNotifyPropertyChanged.

    So it's upsize-friendly.

     

    Tuesday, July 19, 2011 1:52 PM
  • For an ObservableCollection you don't need INotifyPropertyChanged at all, it has inbuilt notification mechanism and at model class, you don't need Observable collection as this is backend stuff and not going to interact with view. 


    Actually you do need INotifyPropertyChanged for the ObserableCollection property.  ObservableCollections have automatic change notifications for collection changed events, but the property itself in the VM still needs to call the PropertyChanged event in the setter or the UI will not update with a new collection.  I do agree that ObservableCollection should not be used in repositories where youi are getting the data.  My repositories normally return an IList<T>.
    Tuesday, July 19, 2011 1:55 PM
  • To answer your questions:

    1. One example that you will be concerned with serialization is if your VM implments the IEditableObject interface so that changes can be rolled back like an Undo function.
    2. Equals is useful when you need to compare VMs for equality or store them in a dictonary.  The qustion of "how often" is not the right question to ask.  Instead you should ask "when it needs to be done, can I do it".  And no, you cannot override the Equals and GetHashCode methods because DOs not only override them but seal them as well.  So you have no access to them.
    3. Multi-threading is another very common practive in application development and there are many cases where you would use multi-threading.  One example would be if you had a data driven UI where you would create WidgetViewModels to represent a Widget in your application.  This proccess could be time consumiung so you would want to place this on a background thread.  In this thread you would create all the WidgetViewModels.  When the widgets have been created you would then use the Dispatcher to add them to the UI thread.  Of course this will not work when your VMs derive from DO.

    There are so many reasons not to use DOs for VMs I could probably write a book on it.  I'm not saying you can't.  By all means, if you want to use DOs then use them.  Just be aware of the limitations. It is not common practice and you really shouldn't be doing it.

    Tuesday, July 19, 2011 2:19 PM
  • IN WPF Binding you must have  a datacontext which is the instanciated class that the XAML in the view uses to bind.  There are differernt methods for datacontext instanciation, but the example above uses the most fundamental method of creating a reference to the namespace and then using the static resource option in the Binding.  This then, at View (Show) time will create a Viewmodel that is considered to be a static resource (not a static class).  This just means that as long as the View is open the Viewmodel is there as a property store.

    There are other more advanced solutions out there but not for the novice.  We won't discuss those unless you are interested.


    JP
    Tuesday, July 19, 2011 4:23 PM
  • Brian is correct in that (and this is a very subtle point) if the collection itself changes say from a Employee to a Customer collection then notification of the View is needed.  However Sanguine is correct too in that if the User at Gui layer or code from behind adds a new item to the collection the internal notifications suffice to update WPF binding system so new item will be displayed automatically.
    JP
    Tuesday, July 19, 2011 4:25 PM
  •  Brian you had mentioned no mulit tasing on DOs, can't the DO spin off a new Task?
    JP
    Tuesday, July 19, 2011 4:27 PM
  • I said you can't create VMs that derive from DO on a separate thread.
    Tuesday, July 19, 2011 4:29 PM