Click here to Skip to main content
15,886,578 members
Articles / Desktop Programming / WPF

MVVM # Episode 1

Rate me:
Please Sign up or sign in to vote.
4.96/5 (104 votes)
3 Dec 2013CPOL19 min read 254.4K   5K   366  
Using an extended MVVM pattern for real world LOB applications: Part 1
using System.Collections.Generic;

namespace ViewModels
{
    /// <summary>
    /// When the VM is closed, the associated V needs to close too
    /// </summary>
    /// <param name="sender"></param>
    public delegate void ViewModelClosingEventHandler(bool? dialogResult);
    /// <summary>
    /// When a pre-existing VM is activated the View needs to activate itself
    /// </summary>
    public delegate void ViewModelActivatingEventHandler();
    /// <summary>
    /// A base class for all view models
    /// </summary>
    public abstract class BaseViewModel : ObservableObject
    {
        public event ViewModelClosingEventHandler ViewModelClosing;
        public event ViewModelActivatingEventHandler ViewModelActivating;

        /// <summary>
        /// Keep a list of any children ViewModels so we can safely remove them when this ViewModel gets closed
        /// </summary>
        private List<BaseViewModel> childViewModels = new List<BaseViewModel>();
        public List<BaseViewModel> ChildViewModels
        {
            get { return childViewModels; }
        }

        #region Bindable Properties

        #region ViewData
        private BaseViewData viewData;
        public BaseViewData ViewData
        {
            get
            {
                return viewData;
            }
            set
            {
                if (value != viewData)
                {
                    viewData = value;
                    base.RaisePropertyChanged("ViewData");
                }

            }
        }
        #endregion
        #endregion
        #region Controller
        /// <summary>
        /// If the ViewModel wants to do anything, it needs a controller
        /// </summary>
        protected IController Controller
        {
            get;
            set;
        }
        #endregion
        #region Constructor
        /// <summary>
        /// Parameterless Constructor required for support of DesignTime versions of View Models
        /// </summary>
        public BaseViewModel()
        {
        }

        /// <summary>
        /// A view model needs a controller reference
        /// </summary>
        /// <param name="controller"></param>
        public BaseViewModel(IController controller)
        {
            Controller = controller;
        }

        /// <summary>
        /// Create the View Model with a Controller and a FrameworkElement (View) injected.
        /// Note that we don't keep a reference to the View - just set its data context and
        /// subscribe it to our Activating and Closing events...
        /// Of course, this means there are references - that must be removed when the view closes,
        /// which is handled in the BaseView
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="view"></param>
        //public BaseViewModel(IController controller, FrameworkElement view)
        public BaseViewModel(IController controller, IView view)
            : this(controller)
        {
            if (view != null)
            {
                view.DataContext = this;
                ViewModelClosing += view.ViewModelClosingHandler;
                ViewModelActivating += view.ViewModelActivatingHandler;
            }
        }
        #endregion
        #region public methods
        /// <summary>
        /// De-Register the VM from the Messenger to avoid non-garbage collected VMs receiving messages
        /// Tell the View (via the ViewModelClosing event) that we're closing.
        /// </summary>
        public void CloseViewModel(bool? dialogResult)
        {
            Controller.Messenger.DeRegister(this);
            if (ViewModelClosing != null)
            {
                ViewModelClosing(dialogResult);
            }
            foreach (var childViewModel in childViewModels)
            {
                childViewModel.CloseViewModel(dialogResult);
            }
        }

        public void ActivateViewModel()
        {
            if (ViewModelActivating != null)
            {
                ViewModelActivating();
            }
        }
        #endregion

    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Devo
Australia Australia
Software developer par excellence,sometime artist, teacher, musician, husband, father and half-life 2 player (in no particular order either of preference or ability)
Started programming aged about 16 on a Commodore Pet.
Self-taught 6500 assembler - wrote Missile Command on the Pet (impressive, if I say so myself, on a text-only screen!)
Progressed to BBC Micro - wrote a number of prize-winning programs - including the best graphics application in one line of basic (it drew 6 multicoloured spheres viewed in perspective)
Trained with the MET Police as a COBOL programmer
Wrote platform game PooperPig which was top of the Ceefax Charts for a while in the UK
Did a number of software dev roles in COBOL
Progressed to Atari ST - learned 68000 assembler & write masked sprite engine.
Worked at Atari ST User magazine as Technical Editor - and was editor of Atari ST World for a while.
Moved on to IBM Mid range for work - working as team leader then project manager
Emigrated to Aus.
Learned RPG programming on the job (by having frequent coffee breaks with the wife!!)
Moved around a few RPG sites
Wrote for PC User magazine - was Shareware Magazine editor for a while.
Organised the first large-scale usage of the Internet in Australia through PC User magazine.
Moved from RPG to Delphi 1
Developed large applications in Delphi before moving on to VB .Net and C#
Became I.T. Manager - realised how boring paper pushing can be
And now I pretty much do .Net development in the daytime, while redeveloping PooperPig for the mobile market at night.

Comments and Discussions