Click here to Skip to main content
15,892,737 members
Articles / Desktop Programming / WPF

MVVM # Episode 3

Rate me:
Please Sign up or sign in to vote.
4.89/5 (19 votes)
13 Dec 2013CPOL12 min read 61.5K   1K   65  
Using an extended MVVM pattern for real world LOB applications: Part 3
using System;
using System.Windows.Input;
using System.Windows.Threading;
using Messengers;


namespace ViewModels
{
    /// <summary>
    /// This view model expects the user to be able to select from a list of 
    /// Customers, sending a message when one is selected.
    /// On selection, the Controller will be asked to show the details of the selected Customer
    /// </summary>
    public class CustomerSelectionViewModel : BaseViewModel
    {
        #region Private Fields
        DispatcherTimer stateFilterTimer;
        #endregion
        #region Properties

        /// <summary>
        /// Just to save us casting the base class's IController to ICustomerController all the time...
        /// </summary>
        private ICustomerController CustomerController
        {
            get
            {
                return (ICustomerController)Controller;
            }
        }

        #region Observable Properties

        private CustomerListItemViewData selectedItem;
        public CustomerListItemViewData SelectedItem
        {
            get
            {
                return selectedItem;
            }
            set
            {
                if (value != selectedItem)
                {
                    selectedItem = value;
                    RaisePropertyChanged("SelectedItem");
                }
            }
        }
        private string stateFilter;
        public string StateFilter
        {
            get
            {
                return stateFilter;
            }
            set
            {
                if (value != stateFilter)
                {
                    stateFilterTimer.Stop();
                    stateFilter = value;
                    RaisePropertyChanged("StateFilter");
                    stateFilterTimer.Start();
                }
            }
        }
        #endregion
        #endregion

        #region Commands
        #region Command Relays
        private RelayCommand userSelectedItemCommand;
        public ICommand UserSelectedItemCommand
        {
            get
            {
                return userSelectedItemCommand ?? (userSelectedItemCommand = new RelayCommand(() => ObeyUserSelectedItemCommand()));
            }
        }
        #endregion
        #region Command Handlers
        private void ObeyUserSelectedItemCommand()
        {
            CustomerController.CustomerSelectedForEdit(this.SelectedItem, this);
        }
        #endregion
        #endregion

        #region Constructors
        /// <summary>
        /// Required to allow our DesignTime version to be instantiated
        /// </summary>
        protected CustomerSelectionViewModel()
        {
        }

        public CustomerSelectionViewModel(ICustomerController controller, string stateFilter = "")
            : this(controller, null, stateFilter)
        {

        }

        /// <summary>
        /// Use the base class to store the controller and set the Data Context of the view (view)
        /// Initialise any data that needs initialising
        /// </summary>
        /// <param name="controller"></param>
        /// <param name="view"></param>
        public CustomerSelectionViewModel(ICustomerController controller, IView view, string stateFilter = "")
            : base(controller, view)
        {
            controller.Messenger.Register(MessageTypes.MSG_CUSTOMER_SAVED, new Action<Message>(RefreshList));
            // Leave it for half a second before filtering on State
            stateFilterTimer = new DispatcherTimer()
            {
                Interval = new TimeSpan(0, 0, 0, 0, 500)
            };
            stateFilterTimer.Tick += StateFilterTimerTick;
            StateFilter = stateFilter;
            RefreshList();
        }
        #endregion

        #region Private Methods
        /// <summary>
        /// Event handler for the timer used for 'filter as you type' on the State filter.
        /// When the timer triggers, filter the list with the existing filter.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void StateFilterTimerTick(object sender, EventArgs e)
        {
            stateFilterTimer.Stop();
            RefreshList();
        }

        private void RefreshList(Message message)
        {
            RefreshList();
            message.HandledStatus = MessageHandledStatus.HandledContinue;
        }

        /// <summary>
        /// Ask for an updated list of customers based on the filter
        /// </summary>
        private void RefreshList()
        {
            ViewData = CustomerController.GetCustomerSelectionViewData(StateFilter);
        }

        #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