Click here to Skip to main content
6,822,613 members and growing! (18,495 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » Windows Presentation Foundation » General     Intermediate License: The Code Project Open License (CPOL)

WPF : If Carlsberg did MVVM Frameworks Part 2 of n

By Sacha Barber

It would probably be like Cinch a MVVM framework for WPF
C# (C#3.0, C#4.0), .NET (.NET3.5, .NET4.0), WPF, Architect, Dev, Design
Revision:30 (See All)
Posted:19 Jul 2009
Updated:23 Dec 2009
Views:50,471
Bookmarked:90 times
Unedited contribution
Prize winner in Competition "Best overall article of July 2009"
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
89 votes for this article.
Popularity: 9.45 Rating: 4.85 out of 5

1

2
6 votes, 6.7%
3
3 votes, 3.4%
4
80 votes, 89.9%
5

Contents

Cinch Article Series Links

  • Cinch primer article
  • A walkthrough of Cinch, and it's internals I (This article)
  • A walkthrough of Cinch, and it's internals II
  • How to develop ViewModels using Cinch
  • How to Unit test ViewModels using Cinch app, including how to test Background work threads which may run within Cinch ViewModels
  • A Demo app using Cinch

    Introduction

    Last time I simply introduced the Cinch the framework article, and this time I stated we would do a walkthrough of Cinch, and it's internals, this is going to be a large article, so it has actually been split over 2 articles. In this article I will be covering the following:

    • Allows view to communicate LifeCycle events to a ViewModel without any hard reference links being maintained, and no IView interface requirements there is no link at all between the View and the ViewModel
    • Has several attached behaviours for common tasks such as
      • Numeric text entry
      • Run an ICommand in a ViewModel based on a RoutedEvent from a XAML FrameworkElement
      • Have a group of such ICommand/RoutedEvent Events for a single XAML FrameworkElement
    • Allows the ViewModel to determine is a Models data should be editable, the UI simple updates via bindings, based on the ViewModel driven editability state. This is available at individual Model field level, so it's very flexible
    • Delegate validation rules which allows validation rules to be as granular as necessary
    • Native IDataErrorInfo support using the Delegate rules approach
    • IEditableObject usage to store/restore object state on edit / cancel edit
    • Weak event creation, to allow the creation of WeakEvents
    • Weak event subscription, which also allows auto unsubscriptions
    • Mediator messaging with WeakReference support out of the box
    So I guess the only way to do this is to just start, so lets get going shall we, but before we do that I just need to repeat the special thanks section, with one addition, Paul Stovell who I forgot to include last time

    PreRequisites

    The demo app makes use of :

    • VS2008 SP1
    • .NET 3.5 SP1
    • SQL server (see the README.txt in the MVVM.DataAccess project to learn what you have to setup for the demo app database)

    Special Thanks

    Before I start I would specifically like to say a massive thanks to the following people, without whom this article and the subsequent series of articles would never have been possible. Basically what I have done with Cinch is studied most of these guys, seen what's hot, what's not, and come up with Cinch. Which I hope adresses some new ground not covered in other frameworks.

    Mark Smith (Julmar Technology), for his excellent MVVM Helper Library, which has helped me enormously. Mark I know I asked your persmission to use some of your code, which you most kindly gave, but I just wanted to say a massive thanks for your cool ideas, some of which I genuinely had not thought of. I take my hat off to you mate.

    Josh Smith / Marlon Grech (as an atomic pair) for their excellent Mediator Implementation. You boys rock, always a pleasure

    Karl Shifflett / Jaime Rodriguez (Microsoft boys) for their excellent MVVM Lob tour, which I attended, well done lads

    Bill Kempf, for just being Bill and being a crazy wizard like programmer, who also has a great MVVM framework called Onyx, which I wrote an article about some time ago. Bill always has the answers, to tough questions, cheers Bill.

    Paul Stovell for his excellent delegate validation idea, which Cinch uses for validation of business objects

    ALL of the WPF Disciples, for being the best online group to belong to IMHO

    Thanks guys/girl, you know who you are

     

    Cinch Internals I

    This section will start the dive into the internals of Cinch. As I say there is far too much for 1 article, so I am splitting the internals of Cinch over 2 articles. Hopefully there will be something of use to you here. Well I hope so anyway.

    View Lifecycle Events

    When developing with the MVVM pattern the holy grail is for there to be no coupling at all between the View and the ViewModel. This clean seperation between View and ViewModel is achieved in Cinch, there is no link between them at all, which is ace. However occasionally it is advantageous for the ViewModel to know something about certain View events, such as :

    • Loaded
    • Activated
    • Deactivated
    • Close

    But we just said that there was no referencing between View/ViewModel and we would like to know about these View events in the ViewModel, so how do we achieve that. The answer lies in attached behaviour. What we do is we have a ICommand based property in the ViewModel and we use an attached View lifecycle behaviour and attach the correct View event to the correct ViewModel ICommand. So when the View event is raised it will actually call a ICommand implementation in the ViewModel.

    Cinch provides for this using 2 things:

    1. A Cinch ViewModel base class called ViewModelBase, which already contains all the View lifecylce ICommand implementation you will need, which I should point out can be overriden is inheritors of the Cinch ViewModelBase class
    2. Some View lifecylcle attached behaviours

    Let us examine one View lifecycle event, Activated, to see how it works, the others are the same.

    Starting with the ViewModelBase class we can see from the code below (extra code removed for clarity) that there is a ICommand called Activated where the trimmed Cinch ViewModelBase looks like this

    namespace Cinch
    {
        /// <summary>
        /// Provides a base class for ViewModels to inherit from. This 
        /// base class provides the following
        /// <list type="Bullet">
        /// <item>Mediator pattern implementation</item>
        /// <item>Service resolution</item>
    
        /// <item>Window lifetime virtual method hooks</item>
        /// <item>INotifyPropertyChanged</item>
        /// </list>
    
        /// </summary>
    
        public abstract class ViewModelBase : INotifyPropertyChanged, IDisposable
        {
    
    	private SimpleCommand activatedCommand;
    
            /// <summary>
            /// Constructs a new ViewModelBase and wires up all the Window based Lifetime
            /// commands such as activatedCommand
    	      /// deactivatedCommand/loadedCommand/closeCommand
            /// </summary>
            public ViewModelBase()
            {
    
    	          activatedCommand = new SimpleCommand
                {
                    CanExecuteDelegate = x => true,
                    ExecuteDelegate = x => OnWindowActivated()
                };
    
    	      }
    
    	
            /// <summary>
    
            /// Allows Window.Activated hook
            /// </summary>
    
            protected virtual void OnWindowActivated()
            {
                //Should be overriden if required in inheritors
            }
    
    
            /// <summary>
            /// ActivatedCommand : Window Lifetime command
            /// </summary>
            public SimpleCommand ActivatedCommand
            {
                get { return activatedCommand; }
            }
    
    
        }
    }
    

    The eagle eyed amongst you may notice that there is a property called ActivatedCommand within the code above, which actually returns a SimpleCommand and not a ICommand that you may have been expecting and maybe even seen in various other posts. This is all cool don't worry, the XAML parser and binding system are clever enough to know that any class that implements ICommand can be used in place of a ICommand in a binding. The reason to expose the ICommand as a SimpleCommand is that the SimpleCommand has an extra property that can be used from inside Unit tests. Namely the CommandSucceeded which is set true on Command execution completion, so can be used in Unit test Assert statements.

    Here is the SimpleCommand code

    using System;
    using System.Windows.Input;
    
    /// <summary>
    /// This class provides a simple
    /// delegate command that implements the ICommand
    /// interface
    /// </summary>
    namespace Cinch
    {
        /// <summary>
        /// Implements the ICommand and wraps up all the verbose stuff so that you 
    
        /// can just pass 2 delegates 1 for the CanExecute and one for the Execute
        /// </summary>
    
        public class SimpleCommand : ICommand
        {
    
            #region Public Properties
            public Boolean CommandSucceeded { get; set; }
    
            /// <summary>
            /// Gets or sets the Predicate to execute when the 
            /// CanExecute of the command gets called
            /// </summary>
            public Predicate<object> CanExecuteDelegate { get; set; }
    
            /// <summary>
            /// Gets or sets the action to be called when the 
            /// Execute method of the command gets called
            /// </summary>
    
            public Action<object> ExecuteDelegate { get; set; }
            #endregion
    
            #region ICommand Members
    
            /// <summary>
            /// Checks if the command Execute method can run
            /// </summary>
            /// <param name="parameter">THe command parameter to be passed</param>
    
            /// <returns>Returns true if the command can execute. 
            /// By default true is returned so that if the user of SimpleCommand 
            /// does not specify a CanExecuteCommand delegate the command 
            /// still executes.</returns>
            public bool CanExecute(object parameter)
            {
                if (CanExecuteDelegate != null)
                    return CanExecuteDelegate(parameter);
                return true;// if there is no can execute default to true
            }
    
            public event EventHandler CanExecuteChanged
            {
                add { CommandManager.RequerySuggested += value; }
                remove { CommandManager.RequerySuggested -= value; }
            }
    
            /// <summary>
            /// Executes the actual command
            /// </summary>
            /// <param name="parameter">THe command parameter to be passed</param>
    
            public void Execute(object parameter)
            {
                if (ExecuteDelegate != null)
                {
                    ExecuteDelegate(parameter);
                    CommandSucceeded = true;
                }
            }
    
            #endregion
        }
    }
    

    Ok so we now have a ViewModel that has a SimpleCommand for Activated that will call a protected virtual void OnWindowActivated() method, but how does this Activated SimpleCommand, get executed, well recall I said there was some attached behaviour magic so lets look at that next.

    Firstly this is how the View would wire up the View Activated attached behavior

    <Window x:Class="MVVM.Demo.Views.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Cinch="clr-namespace:Cinch;assembly=Cinch"
        Title="Window1" Height="300" Width="300">
    
    	  Cinch:LifetimeEvent.Activated="{Binding ActivatedCommand}"
    	  ....
    	  ....
    </Window>
    

    So this will then use the attached View lifecyle event, which is shown below.

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Input;
    
    /// <summary>
    
    /// This allows a Windows lifecycle events to call ICommand(s)
    /// within a ViewModel. This allows the ViewModel to know something
    /// about the Views lifecycle without the need for a strong link
    /// to the actual View
    /// </summary>
    
    namespace Cinch
    {
        /// <summary>
        /// This class is used to attach the Window lifetime events to ICommand implementations.
        /// It allows a ViewModel to hook into the lifetime of the view (when necessary) 
        /// through simple XAML tags.  Supported events are Loaded, Activated, Deactivated 
        /// and Closing/Closed.  For the Closing/Closed event, the CanExecute handler is invoked
        /// in response to the Closing event - if it returns true, then the Closed event is 
        /// allowed and the Execute handler is called in response.
        public static class LifetimeEvent
        {
            
    
            #region Activated
            /// <summary>
            /// Dependency property which holds the ICommand for the Activated event
            /// </summary>
            public static readonly DependencyProperty ActivatedProperty =
                DependencyProperty.RegisterAttached("Activated", 
                typeof(ICommand), typeof(LifetimeEvent),
                    new UIPropertyMetadata(null, OnActivatedEventInfoChanged));
    
            /// <summary>
    
            /// Attached Property getter to retrieve the ICommand
            /// </summary>
            /// <param name="source">Dependency Object</param>
            /// <returns>ICommand</returns>
    
            public static ICommand GetActivated(DependencyObject source)
            {
                return (ICommand)source.GetValue(ActivatedProperty);
            }
    
            /// <summary>
            /// Attached Property setter to change the ICommand
            /// </summary>
            /// <param name="source">Dependency Object</param>
            /// <param name="command">ICommand</param>
    
            public static void SetActivated(DependencyObject source, ICommand command)
            {
                source.SetValue(ActivatedProperty, command);
            }
    
            /// <summary>
            /// This is the property changed handler for the Activated property.
            /// </summary>
            /// <param name="sender">Dependency Object</param>
            /// <param name="e">EventArgs</param>
    
            private static void OnActivatedEventInfoChanged(DependencyObject sender, 
                DependencyPropertyChangedEventArgs e)
            {
                var win = sender as Window;
                if (win != null)
                {
                    win.Activated -= OnWindowActivated;
                    if (e.NewValue != null)
                        win.Activated += OnWindowActivated;
                }
            }
    
            /// <summary>
            /// This is the handler for the Activated event to raise the command.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
    
            private static void OnWindowActivated(object sender, EventArgs e)
            {
                var dpo = (DependencyObject)sender;
                ICommand activatedCommand = GetActivated(dpo);
                if (activatedCommand != null)
                    activatedCommand.Execute(GetCommandParameter(dpo));
            }
            #endregion
    
          
        }
    }
    

    The same mechanism is used for

    • View Deactivated event, where the SimpleCommand in the Cinch ViewModelBase is called DeactivatedCommand, and the virtual method in the Cinch ViewModelBase is called OnWindowDeactivated()
    • View Closing/Closed event, where the SimpleCommand in the Cinch ViewModelBase is called Closeommand, and the virtual method in the Cinch ViewModelBase is called OnWindowClose()
    • View Loaded event, where the SimpleCommand in the Cinch ViewModelBase is called LoadedCommand, and the virtual method in the Cinch ViewModelBase is called OnWindowLoaded()

    Again don't forget there is no standard implementation provided by the Cinch ViewModelBase as this functionality should be performed by overriding these method in a ViewModel which inherits from the Cinch ViewModelBase.

    So ALL you have to do is inherit from Cinch ViewModelBase, and you too can use these View lifecyle events.

    Numeric Textbox Attached Behaviour

    One very common requirement when developing LOb applications is to have numeric only data entry on textboxes. Whilst this is possible to achieve using regular expressions and some code behind and possibly a ValidationRule, wouldn't it just be easier to not let the textbox accept anything apart from numbers in the 1st place. To this end Cinch contains a NumericTextBoxBehavior attached behaviour which looks like this. You should also note that this behaviour caters for pasted text using the DataObject pasting event.

    using System.Windows;
    using System.Windows.Controls.Primitives;
    using System.Windows.Input;
    using System;
    using System.Linq;
    using System.Windows.Controls;
    using System.Text.RegularExpressions;
    
    
    /// <summary>
    /// This forces a TextBoxBase control to be numeric-entry only
    /// By using an attached behaviour
    /// </summary>
    namespace Cinch
    {
        /// <summary>
        /// This forces a TextBoxBase control to be numeric-entry only
        /// </summary>
        /// <example>
        /// <![CDATA[  <TextBox Cinch:NumericTextBoxBehavior.IsEnabled="True" />  ]]>
        /// </example>
        public static class NumericTextBoxBehavior
        {
            #region IsEnabled DP
            /// <summary>
            /// Dependency Property for turning on numeric behavior in a TextBox.
            /// </summary>
            public static readonly DependencyProperty IsEnabledProperty =
                DependencyProperty.RegisterAttached("IsEnabled",
                    typeof(bool), typeof(NumericTextBoxBehavior),
                        new UIPropertyMetadata(false, OnEnabledStateChanged));
    
            /// <summary>
            /// Attached Property getter for the IsEnabled property.
            /// </summary>
            /// <param name="source">Dependency Object</param>
            /// <returns>Current property value</returns>
            public static bool GetIsEnabled(DependencyObject source)
            {
                return (bool)source.GetValue(IsEnabledProperty);
            }
    
            /// <summary>
            /// Attached Property setter for the IsEnabled property.
            /// </summary>
            /// <param name="source">Dependency Object</param>
            /// <param name="value">Value to set on the object</param>
            public static void SetIsEnabled(DependencyObject source, bool value)
            {
                source.SetValue(IsEnabledProperty, value);
            }
    
            /// <summary>
            /// This is the property changed handler for the IsEnabled property.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private static void OnEnabledStateChanged(DependencyObject sender,
                DependencyPropertyChangedEventArgs e)
            {
                TextBox tb = sender as TextBox;
                if (tb == null)
                    return;
    
                tb.PreviewTextInput -= tbb_PreviewTextInput;
                DataObject.RemovePastingHandler(tb, OnClipboardPaste);
    
                bool b = ((e.NewValue != null && e.NewValue.GetType() == typeof(bool))) ?
                    (bool)e.NewValue : false;
                if (b)
                {
                    tb.PreviewTextInput += tbb_PreviewTextInput;
                    DataObject.AddPastingHandler(tb, OnClipboardPaste);
                }
            }
    
            #endregion
    
            #region Private Methods
    
            /// <summary>
            /// This method handles paste and drag/drop events onto the TextBox.  It restricts the character
            /// set to numerics and ensures we have consistent behavior.
            /// </summary>
            /// <param name="sender">TextBox sender</param>
            /// <param name="e">EventArgs</param>
            private static void OnClipboardPaste(object sender, DataObjectPastingEventArgs e)
            {
                TextBox tb = sender as TextBox;
                string text = e.SourceDataObject.GetData(e.FormatToApply) as string;
    
                if (tb != null && !string.IsNullOrEmpty(text) && !Validate(tb, text))
                    e.CancelCommand();
            }
    
            /// <summary>
            /// This checks if the resulting string will match the regex expression
            /// </summary>
            static void tbb_PreviewTextInput(object sender, TextCompositionEventArgs e)
            {
                TextBox tb = sender as TextBox;
    
                if (tb != null && !Validate(tb, e.Text))
                    e.Handled = true;
            }
    
            #endregion
    
            private static bool Validate(TextBox tb, string newContent)
            {
                string testString = string.Empty;
                // replace selection with new text.
                if (!string.IsNullOrEmpty(tb.SelectedText))
                {
                    string pre = tb.Text.Substring(0, tb.SelectionStart);
                    string after = tb.Text.Substring(tb.SelectionStart + tb.SelectionLength, tb.Text.Length - (tb.SelectionStart + tb.SelectionLength));
                    testString = pre + newContent + after;
                }
                else
                {
                    string pre = tb.Text.Substring(0, tb.CaretIndex);
                    string after = tb.Text.Substring(tb.CaretIndex, tb.Text.Length - tb.CaretIndex);
                    testString = pre + newContent + after;
                }
    
                Regex regExpr = new Regex(@"^([-+]?)(\d*)([,.]?)(\d*)$");
                if (regExpr.IsMatch(testString))
                    return true;
    
                return false;
            }
        }
    }
    

    Which can easily be applied to a textbox in your application as follows:

    <Window x:Class="MVVM.Demo.Views.Window1"
    
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Cinch="clr-namespace:Cinch;assembly=Cinch"
    
        Title="Window1" Height="300" Width="300">
    
        <Grid>
    
            <TextBox Cinch:NumericTextBoxBehavior.IsEnabled="True" />
    
        </Grid>
    </Window>
    

    With this attached behaviour enabled only numeric data entry will be allowed for the textbox that has the NumericTextBoxBehavior attached behaviour applied.

    Attached Command Behaviour

    Continuing with the attached behaviors it is also sometimes very convenient to be able to fire a ViewModel ICommand from a FrameworkElement RoutedEvent. This is something that the WPF framework does not do out of the box, though Blend 3 does allow this by the use of Blend Interactivity dll. If you want an example of that have a look at my blog post WPF : Blend 3 Interactions / Behaviours

    But we are where we are, and I want people to know how to do this without using a non released Dll from a different product that will more than likely find its way into WPF proper at some stage. So lets continue with how to do it without the Blend Interactivity dll.

    So here is how, Cinch actually provides 2 alternatives here, attaching a single ICommand to a single FrameworkElement RoutedEvent, or attaching a collection of ICommands to a FrameworkElement using different RoutedEvents.

    Lets start simple, and build up from there.

    Attaching a single ICommand to a single FrameworkElement RoutedEvent

    This is easily done via yet another attached property or 2, which you can set on a View FrameworkElement like this.

    <Window x:Class="MVVM.Demo.Views.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    
        xmlns:Cinch="clr-namespace:Cinch;assembly=Cinch"
        Title="Window1" Height="300" Width="300">
    
         <Grid Background="WhiteSmoke"
    
           	Cinch:SingleEventCommand.RoutedEventName="MouseDown"
              Cinch:SingleEventCommand.TheCommandToRun=
               "{Binding Path=ShowWindowCommand}"/>
    
    </Window>
    
    

    So we set the RoutedEvent to fire the ICommand and we set the ViewModel ICommand to execute via a Binding.

    So all that is left is to look at how this is achieved, which is done with a standard DP or 2 and a touch of Reflection to get the RoutedEvent from the DependencyObject that declares the RoutedEventName attached DP, and from there we just create a Delegate which is called when the event is raised, which in turn fires the ICommand that was specified using the TheCommandToRun DP.

    Here is the code.

    public static class SingleEventCommand
    {
        #region TheCommandToRun
    
        /// <summary>
        /// TheCommandToRun : The actual ICommand to run
        /// </summary>
        public static readonly DependencyProperty TheCommandToRunProperty =
            DependencyProperty.RegisterAttached("TheCommandToRun", 
                typeof(ICommand),
                typeof(SingleEventCommand),
                new FrameworkPropertyMetadata((ICommand)null));
    
        /// <summary>
    
        /// Gets the TheCommandToRun property.  
        /// </summary>
        public static ICommand GetTheCommandToRun(DependencyObject d)
        {
            return (ICommand)d.GetValue(TheCommandToRunProperty);
        }
    
        /// <summary>
        /// Sets the TheCommandToRun property.  
        /// </summary>
        public static void SetTheCommandToRun(DependencyObject d, ICommand value)
        {
            d.SetValue(TheCommandToRunProperty, value);
        }
        #endregion
    
        #region RoutedEventName
    
        /// <summary>
    
        /// RoutedEventName : The event that should actually execute the
        /// ICommand
        /// </summary>
    
        public static readonly DependencyProperty RoutedEventNameProperty =
            DependencyProperty.RegisterAttached("RoutedEventName", typeof(String),
            typeof(SingleEventCommand),
                new FrameworkPropertyMetadata((String)String.Empty,
                    new PropertyChangedCallback(OnRoutedEventNameChanged)));
    
        /// <summary>
        /// Gets the RoutedEventName property.  
        /// </summary>
        public static String GetRoutedEventName(DependencyObject d)
        {
            return (String)d.GetValue(RoutedEventNameProperty);
        }
    
        /// <summary>
    
        /// Sets the RoutedEventName property.  
        /// </summary>
    
        public static void SetRoutedEventName(DependencyObject d, String value)
        {
            d.SetValue(RoutedEventNameProperty, value);
        }
    
        /// <summary>
        /// Hooks up a Dynamically created EventHandler (by using the 
        /// <see cref="EventHooker">EventHooker</see> class) that when
        /// run will run the associated ICommand
        /// </summary>
    
        private static void OnRoutedEventNameChanged(DependencyObject d, 
            DependencyPropertyChangedEventArgs e)
        {
            String routedEvent = (String)e.NewValue;
    
            if (d == null || String.IsNullOrEmpty(routedEvent))
                return;
    
            
            //If the RoutedEvent string is not null, create a new
            //dynamically created EventHandler that when run will execute
            //the actual bound ICommand instance (usually in the ViewModel)
            EventHooker eventHooker = new EventHooker();
            eventHooker.ObjectWithAttachedCommand = d;
    
            EventInfo eventInfo = d.GetType().GetEvent(routedEvent, 
                BindingFlags.Public | BindingFlags.Instance);
    
            //Hook up Dynamically created event handler
            if (eventInfo != null)
            {
                eventInfo.RemoveEventHandler(d,
                    eventHooker.GetNewEventHandlerToRunCommand(eventInfo));
    
                eventInfo.AddEventHandler(d,
                    eventHooker.GetNewEventHandlerToRunCommand(eventInfo));
            }
    
        }
        #endregion
    }
    
    /// <summary>
    
    /// Contains the event that is hooked into the source RoutedEvent
    /// that was specified to run the ICommand
    /// </summary>
    sealed class EventHooker
    {
        #region Public Methods/Properties
        /// <summary>
        /// The DependencyObject, that holds a binding to the actual
        /// ICommand to execute
        /// </summary>
        public DependencyObject ObjectWithAttachedCommand { get; set; }
    
        /// <summary>
    
        /// Creates a Dynamic EventHandler that will be run the ICommand
        /// when the user specified RoutedEvent fires
        /// </summary>
    
        /// <param name="eventInfo">The specified RoutedEvent EventInfo</param>
        /// <returns>An Delegate that points to a new EventHandler
        /// that will be run the ICommand</returns>
    
        public Delegate GetNewEventHandlerToRunCommand(EventInfo eventInfo)
        {
            Delegate del = null;
    
            if (eventInfo == null)
                throw new ArgumentNullException("eventInfo");
    
            if (eventInfo.EventHandlerType == null)
                throw new ArgumentException("EventHandlerType is null");
    
            if (del == null)
                del = Delegate.CreateDelegate(eventInfo.EventHandlerType, this,
                      GetType().GetMethod("OnEventRaised",
                        BindingFlags.NonPublic | 
                        BindingFlags.Instance));
    
            return del;
        }
        #endregion
    
        #region Private Methods
    
        /// <summary>
    
        /// Runs the ICommand when the requested RoutedEvent fires
        /// </summary>
        private void OnEventRaised(object sender, EventArgs e)
        {
            ICommand command = (ICommand)(sender as DependencyObject).
                GetValue(SingleEventCommand.TheCommandToRunProperty);
    
            if (command != null)
            {
                command.Execute(null);
            }
        }
        #endregion
    }
    
    

    So this allows a single FrameworkElement RoutedEvent to fire a single ViewModel ICommand, but Cinch does more than that. So lets look at the more advanced scenario.

    Attaching a collection of ICommand(s) to a FrameworkElement using different RoutedEvent(s)

    As before let us see how you would use the attached collection of ICommands/RoutedEvents from a View. Here is how you might do that.

    <Window x:Class="MVVM.Demo.Views.Window1"
    
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Cinch="clr-namespace:Cinch;assembly=Cinch"
    
        Title="Window1" Height="300" Width="300">
    
        <Grid Background="WhiteSmoke">
           <Behaviors:EventCommander.Mappings>
    
              <Behaviors:CommandEvent 
                  Command="{Binding MouseEnterCommand}" 
                  Event="MouseEnter" />
    
              <Behaviors:CommandEvent 
                  Command="{Binding MouseLeaveCommand}" 
                  Event="MouseLeave" />
    
           </Behaviors:EventCommander.Mappings>
        </Grid>
    
    </Window>
    

    So you can see that this time, there is an attached property (EventCommander.Mappings) that is expecting a collection of CommandEvent objects. The concept behind this is largely the same, except this time there is a collection of these CommandEvent objects, but they largely work the same as just described above, so I will concentrate on how the EventCommander.Mappings collection works, and assume the discussion above was enough to explain a single CommandEvent object.

    The EventCommander.Mappings collection, looks like this:

    public static class EventCommander
    {
        #region InternalMappings DP
        // Make it internal so WPF ignores the property and always uses the 
        //public getter/setter.  This is per John Gossman blog post - 07/2008.
        internal static readonly DependencyProperty MappingsProperty = 
            DependencyProperty.RegisterAttached("InternalMappings", 
                            typeof(CommandEventCollection), typeof(EventCommander),
                            new UIPropertyMetadata(null, OnMappingsChanged));
    
        /// <summary>
        /// Retrieves the mapping collection
        /// </summary>
        /// <param name="obj"></param>
    
        /// <returns></returns>
        internal static CommandEventCollection InternalGetMappingCollection(
            DependencyObject obj)
        {
            var map = obj.GetValue(MappingsProperty) as CommandEventCollection;
            if (map == null)
            {
                map = new CommandEventCollection();
                SetMappings(obj, map);
            }
            return map;
        }
    
        /// <summary>
        /// This retrieves the mapping collection
        /// </summary>
        /// <param name="obj">Dependency Object</param>
    
        /// <returns>Mapping collection</returns>
        public static IList GetMappings(DependencyObject obj)
        {
            return InternalGetMappingCollection(obj);
        }
    
        /// <summary>
        /// This sets the mapping collection.
        /// </summary>
        /// <param name="obj">Dependency Object</param>
    
        /// <param name="value">Mapping collection</param>
        public static void SetMappings(DependencyObject obj, 
            CommandEventCollection value)
        {
            obj.SetValue(MappingsProperty, value);
        }
    
        /// <summary>
        /// This changes the event mapping
        /// </summary>
        /// <param name="target"></param>
    
        /// <param name="e"></param>
        private static void OnMappingsChanged(DependencyObject target, 
            DependencyPropertyChangedEventArgs e)
        {
            if (e.OldValue != null)
            {
                CommandEventCollection cec = e.OldValue as CommandEventCollection;
                if (cec != null)
                    cec.Unsubscribe(target);
            }
            if (e.NewValue != null)
            {
                CommandEventCollection cec = e.NewValue as CommandEventCollection;
                if (cec != null)
                    cec.Subscribe(target);
            }
        }
        #endregion
    }

    Where it can be seen that behind the scenes the EventCommander.Mappings collection is populating a CommandEventCollection. The CommandEventCollection inherits from Freezable, as this is a trick you can use to get DataContext inheritence. Basically what happens is that by inheriting from Freezable a non UI element will also get the current UI elements DataContext (which is more that likely the ViewModel). If you did not inherit from Freezable, the CommandEventCollection would not be able to pick up the ViewModels bound ICommand, as it would know nothing about a current DataContext object, it would be null. It's a trick, but it works. If you want to know more read Mike Hillbergs blog entry Mike Hillbergs Freezable blog post and maybe have a look at Josh Smiths DataContextSpy post, which is also very useful.

    Anyway the which CommandEventCollection looks like this, where its main job is to maintain the list of current CommandEvents.

    public class CommandEventCollection : FreezableCollection<CommandEvent>
    {
        #region Data
        private object _target;
        private readonly List<CommandEvent> _currentList = new List<CommandEvent>();
        #endregion
    
        #region Ctor
        /// <summary>
    
        /// Constructor
        /// </summary>
        public CommandEventCollection()
        {
            ((INotifyCollectionChanged)this).CollectionChanged += OnCollectionChanged;
        }
        #endregion
    
        #region Private/Internal Methods
        /// <summary>
        /// Wire up events to the target
        /// </summary>
        /// <param name="target"></param>
    
        internal void Subscribe(object target)
        {
            _target = target;
            foreach(var item in this)
                item.Subscribe(target);
        }
    
        /// <summary>
        /// Unwire all target events
        /// </summary>
        /// <param name="target"></param>
        internal void Unsubscribe(object target)
        {
            foreach (var item in this)
                item.Unsubscribe(target);
            _target = null;
        }
    
        /// <summary>
    
        /// This handles the collection change event - it then subscribes and unsubscribes events.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
    
        private void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (var item in e.NewItems)
                        OnItemAdded((CommandEvent)item);
                    break;
    
                case NotifyCollectionChangedAction.Remove:
                    foreach (var item in e.OldItems)
                        OnItemRemoved((CommandEvent)item);
                    break;
    
                case NotifyCollectionChangedAction.Replace:
                    foreach (var item in e.OldItems)
                        OnItemRemoved((CommandEvent)item);
                    foreach (var item in e.NewItems)
                        OnItemAdded((CommandEvent)item);
                    break;
    
                case NotifyCollectionChangedAction.Move:
                    break;
    
                case NotifyCollectionChangedAction.Reset:
                    _currentList.ForEach(i => i.Unsubscribe(_target));
                    _currentList.Clear();
                    foreach (var item in this)
                        OnItemAdded(item);
                    break;
    
                default:
                    return;
            }
        }
    
        /// <summary>
    
        /// A new item has been added to the event list
        /// </summary>
        /// <param name="item"></param>
    
        private void OnItemAdded(CommandEvent item)
        {
            if (item != null && _target != null)
            {
                _currentList.Add(item);
                item.Subscribe(_target);                
            }
        }
    
        /// <summary>
        /// An item has been removed from the event list.
        /// </summary>
    
        /// <param name="item"></param>
    
        private void OnItemRemoved(CommandEvent item)
        {
            if (item != null && _target != null)
            {
                _currentList.Remove(item);
                item.Unsubscribe(_target);
            }
        }
        #endregion
    }

    In case any of you are wondering how to obtain and use the RoutedEventArgs and pass them as the ICommand parameter to the ViewModel where the Command is, Marlon Grech (fellow WPF Disciple and all round great chap), has a lovely post which is at this url :http://marlongrech.wordpress.com/2009/07/03/how-to-get-the-eventargs-as-a-commandparameter-using-the-attachedcommandbehaviour/

    Better INPC, No Magic Strings

    When working with WPF it is very common to have your ViewModel/Model classes implement the System.ComponentModel.INotifyPropertyChanged interface for binding notification of property changes. This is typically implemented like this:

    using System.ComponentModel;
    
    namespace SDKSample
    {
      // This class implements INotifyPropertyChanged
      // to support one-way and two-way bindings
      // (such that the UI element updates when the source
      // has been changed dynamically)
      public class Person : INotifyPropertyChanged
      {
          private string name;
          // Declare the event
          public event PropertyChangedEventHandler PropertyChanged;
    
          public Person()
          {
          }
    
          public Person(string value)
          {
              this.name = value;
          }
    
          public string PersonName
          {
              get { return name; }
              set
              {
                  name = value;
                  // Call OnPropertyChanged whenever the property is updated
                  OnPropertyChanged("PersonName");
              }
          }
    
          // Create the OnPropertyChanged method to raise the event
          protected void OnPropertyChanged(string name)
          {
              PropertyChangedEventHandler handler = PropertyChanged;
              if (handler != null)
              {
                  handler(this, new PropertyChangedEventArgs(name));
              }
          }
      }
    }
      

    The problem with this approach is that the code has magic string in it which are easy to get wrong. Have a look at the OnPropertyChanged("PersonName"); code shown above. I had originally being using some static reflection by using LINQ expression trees to obtain the property name, I was using Bill Kempfs excellent Reflect code. The problem with the static reflection Expression tree thing is that it is slow to create the eventArgs each time. One of the readers of this article actually came up with a better solutuion where the INPC EventArgs are created once and then re-used. I liked this idea a lot, so have now included it in Cinch. The readers post is available here if you want some more information abouts this

    CinchII.aspx?msg=3141144#xx3141144xx

    Cinch now uses this approach. Here is how it works. there is a static helper class which looks like this

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Linq.Expressions;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Reflection;
    
    namespace Cinch
    {
        /// <summary>
        /// A small helper class that has a method to help create
        /// PropertyChangedEventArgs when using the INotifyPropertyChanged
        /// interface
        /// </summary>
        public static class ObservableHelper
        {
            #region Public Methods
            /// <summary>
            /// Creates PropertyChangedEventArgs
            /// </summary>
            /// <param name="propertyExpression">Expression to make 
            /// PropertyChangedEventArgs out of</param>
            /// <returns>PropertyChangedEventArgs</returns>
            public static PropertyChangedEventArgs CreateArgs<T>(
                Expression<Func<T, Object>> propertyExpression)
            {
                return new PropertyChangedEventArgs(
                    GetPropertyName<T>(propertyExpression));
            }
    
            /// <summary>
            /// Creates PropertyChangedEventArgs
            /// </summary>
            /// <param name="propertyExpression">Expression to make 
            /// PropertyChangedEventArgs out of</param>
            /// <returns>PropertyChangedEventArgs</returns>
            public static string GetPropertyName<T>(
                Expression<Func<T, Object>> propertyExpression)
            {
                var lambda = propertyExpression as LambdaExpression;
                MemberExpression memberExpression;
                if (lambda.Body is UnaryExpression)
                {
                    var unaryExpression = lambda.Body as UnaryExpression;
                    memberExpression = unaryExpression.Operand as MemberExpression;
                }
                else
                {
                    memberExpression = lambda.Body as MemberExpression;
                }
    
                var propertyInfo = memberExpression.Member as PropertyInfo;
    
                return propertyInfo.Name;
            }
    
            #endregion
        }
    }
    

    Which we can then use like this from any property

    static PropertyChangedEventArgs currentCustomerChangeArgs =
        ObservableHelper.CreateArgs<AddEditOrderViewModel>(x => x.CurrentCustomer);
    
    public CustomerModel CurrentCustomer
    {
        get { return currentCustomer; }
        set
        {
            currentCustomer = value;
            NotifyPropertyChanged(currentCustomerChangeArgs);
        }
    }
      

    No more magic strings, at all. Most excellent.

    ViewModel Modes

    One of the things I have always struggled with when working with MVVM and using it to produce LOB apps, is View mode. For example it would be nice to have a View that is read only and then the user clicks edit and then all the fields on the View are editable. Now this could be achieved by having a command in the ViewModel that changes from ReadOnly mode to EditMode say, and all the UIElements on the View could bind to some CurrentMode property on the ViewModel. Sounds do'able, but as we all know things are never as clean cut as that. In my workplace, we have complicated requirements around data entry and there is no way a single mode can be applied to all data entry fields on a single View, no way, we need very granular data entry rights, down to individual field level.

    So this got me thinking, what we need is a editable state for each data item in a UI Model. I thought about this some more and came up with a generic wrapper class which wraps a single property but also exposes a IsEditable property. Now the ViewModel can access these wrappers as they are public properties on either a UI Model classes or actually public properties in the ViewModel (I expose a CurrentX object of my ViewModel, but others repeat all the UI Model properties in the ViewModel. Me I have no issues with writing straight from the View to the Model, providing it doesn't get to the database if its InValid), so it can bind its data to the wrappers data property and can disable data entry based on the wrappers IsEditable property.

    To this end I came up with a simple class that looks like this.

          /// <summary>
        /// Abstract base class for DataWrapper - allows easier access to
        /// methods for the DataWrapperHelper.
        /// </summary>
        public abstract class DataWrapperBase : EditableValidatingObject
        {
            #region Data
            private Boolean isEditable = false;
    
            private IParentablePropertyExposer parent = null;
            private PropertyChangedEventArgs parentPropertyChangeArgs = null;
            #endregion
    
            #region Ctors
            public DataWrapperBase()
            {
            }
    
            public DataWrapperBase(IParentablePropertyExposer parent,
                PropertyChangedEventArgs parentPropertyChangeArgs)
            {
                this.parent = parent;
                this.parentPropertyChangeArgs = parentPropertyChangeArgs;
            }
            #endregion
    
            #region Protected Methods
    
            /// <summary>
            /// Notifies all the parent (INPC) objects INotifyPropertyChanged.PropertyChanged subscribed delegates
            /// that an internal DataWrapper property value has changed, which in turn raises the appropriate
            /// INotifyPropertyChanged.PropertyChanged event on the parent (INPC) object
            /// </summary>
            protected internal void NotifyParentPropertyChanged()
            {
                if (parent == null || parentPropertyChangeArgs == null)
                    return;
    
                //notify all delegates listening to DataWrapper<T> parent objects PropertyChanged
                //event
                Delegate[] subscribers = parent.GetINPCSubscribers();
                if (subscribers != null)
                {
                    foreach (PropertyChangedEventHandler d in subscribers)
                    {
                        d(parent, parentPropertyChangeArgs);
                    }
                }
            }
    
            #endregion
    
            #region Public Properties
    
            /// <summary>
            /// The editable state of the data, the View
            /// is expected to use this to enable/disable
            /// data entry. The ViewModel would set this
            /// property
            /// </summary>
            static PropertyChangedEventArgs isEditableChangeArgs =
                ObservableHelper.CreateArgs<DataWrapperBase>(x => x.IsEditable);
    
            public Boolean IsEditable
            {
                get { return isEditable; }
                set
                {
                    if (isEditable != value)
                    {
                        isEditable = value;
                        NotifyPropertyChanged(isEditableChangeArgs);
                        NotifyParentPropertyChanged();
                    }
                }
    
            }
            #endregion
        }
    
        /// <summary>
        /// This interface is here so to ensure that both DataWrapper of T
        /// and DataWrapperExt of T have a commonly named property for
        /// the data (DataValue) and that we can safely retrieve this
        /// name elsewhere via static reflection.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public interface IDataWrapper<T>
        {
            T DataValue { get; set; }
        }
    
    
        /// <summary>
        /// This interface is implemented by both the 
        /// <see cref="ValidatingObject">ValidatingObject</see> and the
        /// <see cref="ViewModelBase">ViewModelBase</see> classes, and is used
        /// to expose the list of delegates that are currently listening to the
        /// <see cref="System.ComponentModel.INotifyPropertyChanged">INotifyPropertyChanged</see>
        /// PropertyChanged event. This is done so that the internal 
        /// <see cref="DataWrapper">DataWrapper</see> classes can notify their parent object
        /// when an internal <see cref="DataWrapper">DataWrapper</see> property changes
        /// </summary>
        public interface IParentablePropertyExposer
        {
            Delegate[] GetINPCSubscribers();
        }
    
    
        /// <summary>
        /// Provides a wrapper around a single piece of data
        /// such that the ViewModel can put the data item
        /// into a editable state and the View can bind to
        /// both the DataValue for the actual Value, and to 
        /// the IsEditable to determine if the control which
        /// has the data is allowed to be used for entering data.
    
    
    
        /// 
        /// The Viewmodel is expected to set the state of the
        /// IsEditable property for all DataWrappers in a given Model
        /// </summary>
        /// <typeparam name="T">The type of the Data</typeparam>
        public class DataWrapper<T> : DataWrapperBase, IDataWrapper<T>
        {
            #region Data
            private T dataValue = default(T);
            #endregion
    
            #region Ctors
            public DataWrapper()
            {
            }
    
            public DataWrapper(T initialValue)
            {
                dataValue = initialValue;
            }
    
            public DataWrapper(IParentablePropertyExposer parent,
                PropertyChangedEventArgs parentPropertyChangeArgs)
                : base(parent, parentPropertyChangeArgs)
            {
            }
            #endregion
    
            #region Public Properties
            /// <summary>
            /// The actual data value, the View is
            /// expected to bind to this to display data
            /// </summary>
            static PropertyChangedEventArgs dataValueChangeArgs =
                ObservableHelper.CreateArgs<DataWrapper<T>>(x => x.DataValue);
    
            public T DataValue
            {
                get { return dataValue; }
                set
                {
                    dataValue = value;
                    NotifyPropertyChanged(dataValueChangeArgs);
                    NotifyParentPropertyChanged();
                }
            }
            #endregion
    
    
    

    Which can then be used as properties on your UI Model classes (or directly on the ViewModel if you want to), like this, (don't worry about the inheriting from Cinch.EditableValidatingObject, we'll get to that soon)

    public class OrderModel : Cinch.EditableValidatingObject
    {
    
        //Any data item is declared as a Cinch.DataWrapper, to allow the ViewModel
        //to decide what state the data is in, and the View just renders 
        //the data state accordingly
        private Cinch.DataWrapper<Int32> quantity;
    
    
        public OrderModel()
        {
    		Quantity = new DataWrapper(this, quantityChangeArgs);
    		....
    		....
    		//Setup rules etc etc
    		
        }
    
        static PropertyChangedEventArgs quantityChangeArgs =
            ObservableHelper.CreateArgs<OrderModel>(x => x.Quantity);
    
        public Cinch.DataWrapper<Int32> Quantity
        {
            get { return quantity; }
            private set
            {
                quantity = value;
                NotifyPropertyChanged(quantityChangeArgs);
            }
        }
    
    
    }

    Notice the setter is private, this is due to the fact that these object are immutable, and are only allowed to be set in the constructor. The IsEditable and the DataValue can be changed whenever you like though. The other thing to note is that the Model/ViewModel actually uses some reflection on construction to obtain a IEnumerable<DataWrapperBase> which is then used as a cache so setting any of the cached DataWrapper<T> properties from that point on is very quick. This is achieved as follows:

    In the condtrcutor we have something like this:

    using System;
    
    using Cinch;
    using MVVM.DataAccess;
    using System.ComponentModel;
    using System.Collections.Generic;
    
    namespace MVVM.Models
    {
        /// <summary>
        /// Respresents a UI Order Model, which has all the
        /// good stuff like Validation/INotifyPropertyChanged/IEditableObject
        /// which are all ready to use within the base class.
        /// 
        /// This class also makes use of <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see>s. Where the idea is that the ViewModel
        /// is able to control the mode for the data, and as such the View
        /// simply binds to a instance of a <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see> for both its data and its editable state.
        /// Where the View can disable a control based on the 
        /// <see cref="Cinch.DataWrapper">Cinch.DataWrapper</see> editable state.
        /// </summary>
        public class OrderModel : Cinch.EditableValidatingObject
        {
            #region Data
            //Any data item is declared as a Cinch.DataWrapper, to allow the ViewModel
            //to decide what state the data is in, and the View just renders 
            //the data state accordingly
            private Cinch.DataWrapper<Int32> orderId;
            private Cinch.DataWrapper<Int32> customerId;
            private Cinch.DataWrapper<Int32> productId;
            private Cinch.DataWrapper<Int32> quantity;
            private Cinch.DataWrapper<DateTime> deliveryDate;
            private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
            #endregion
    
            #region Ctor
            public OrderModel()
            {
                #region Create DataWrappers
    
                OrderId = new DataWrapper<Int32>(this, orderIdChangeArgs);
                CustomerId = new DataWrapper<Int32>(this, customerIdChangeArgs);
                ProductId = new DataWrapper<Int32>(this, productIdChangeArgs);
                Quantity = new DataWrapper<Int32>(this, quantityChangeArgs);
                DeliveryDate = new DataWrapper<DateTime>(this, deliveryDateChangeArgs);
    
                //fetch list of all DataWrappers, so they can be used again later without the
                //need for reflection
                cachedListOfDataWrappers =
                    DataWrapperHelper.GetWrapperProperties<OrderModel>(this);
    
                #endregion
    
       
            }
            #endregion
    
    
        }
    }
    

    And then from then on whenever we deal with the DataWrapper<T> properties we can use the cached list.

    So getting back to how we might use these in our Views, I simply bind to these DataWrapper<T> properties as follows:

    <TextBox FontWeight="Normal" FontSize="11" Width="200"
        Cinch:NumericTextBoxBehavior.IsEnabled="True"            
        Text="{Binding Path=CurrentCustomerOrder.Quantity.DataValue,
        UpdateSourceTrigger=LostFocus, ValidatesOnDataErrors=True,
        ValidatesOnExceptions=True}"
    
        Style="{StaticResource ValidatingTextBox}"
        IsEnabled="{Binding Path=CurrentCustomerOrder.Quantity.IsEditable}"/>
    	

    So that's all cool, but how do these DataWrapper<T> objects respond to a change in mode state. Well that is quite simply actually, we do have a Cinch.ViewMode in the ViewModel and whenever that changes state, we need to update the state of all the nested DataWrapper<T> objects in whatever object is is we are trying to change the state for (for me this is always a UI Model, for others this may be the ViewModel itself).

    Here is an example AddEditOrderViewModel, which for me holds a single UI Model of type OrderModel, as I say others will not like this and would have the ViewModel expose all the properties available within a UI Model of type OrderModel. The thing with MVVM is that you do it your own way, and this is my way. I don't care if InValid data gets to the Model just so long as that Model can not be saved to the database.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows.Data;
    using System.Linq;
    
    using Cinch;
    using MVVM.Models;
    using MVVM.DataAccess;
    
    
    namespace MVVM.ViewModels
    {
        /// <summary>
        /// Provides ALL logic for the AddEditOrderView
        /// </summary>
        public class AddEditOrderViewModel : Cinch.WorkspaceViewModel
        {
    
            private ViewMode currentViewMode = ViewMode.AddMode;
    
            private OrderModel currentCustomerOrder;
    
    
    
            public AddEditOrderViewModel()
            {
    
            }
    
              /// <summary>
            /// The current ViewMode, when changed will loop
            /// through all nested DataWrapper objects and change
            /// their state also
            /// </summary>
    
            static PropertyChangedEventArgs currentViewModeChangeArgs =
                ObservableHelper.CreateArgs<AddEditOrderViewModel>(x => x.CurrentViewMode);
    
            public ViewMode CurrentViewMode
            {
                get { return currentViewMode; }
                set
                {
                    currentViewMode = value;
    
                    switch (currentViewMode)
                    {
                        case ViewMode.AddMode:
                            CurrentCustomerOrder = new OrderModel();
                            this.DisplayName = "Add Order";
                            break;
                        case ViewMode.EditMode:
                            CurrentCustomerOrder.BeginEdit();
                            this.DisplayName = "Edit Order";
                            break;
                        case ViewMode.ViewOnlyMode:
                            this.DisplayName = "View Order";
                            break;
                    }
    
                    //Now change all the CurrentCustomer.CachedListOfDataWrappers
                    //Which sets all the Cinch.DataWrapper<T>s to the correct IsEditable
                    //state based on the new ViewMode applied to the ViewModel
                    //we can use the Cinch.DataWrapperHelper class for this
                    DataWrapperHelper.SetMode(
                        CurrentCustomer.CachedListOfDataWrappers,
                        currentViewMode);
    
                    NotifyPropertyChanged(currentViewModeChangeArgs);
                }
            }
    
            /// <summary>
    
            /// Current Customer OrderModel
            /// </summary>
            static PropertyChangedEventArgs currentCustomerOrderChangeArgs =
                ObservableHelper.CreateArgs<AddEditOrderViewModel>(x => x.CurrentCustomerOrder);
    
            public OrderModel CurrentCustomerOrder
            {
                get { return currentCustomerOrder; }
                set
                {
                    currentCustomerOrder = value;
                    if (currentCustomerOrder != null)
                    {
                        if (currentCustomerOrder.ProductId.DataValue > 0)
                        {
                            ProductModel prod = this.Products.Where(p => p.ProductId ==
                                currentCustomerOrder.ProductId.DataValue).Single();
                            productsCV.MoveCurrentTo(prod);
                        }
                    }
                    NotifyPropertyChanged(currentCustomerOrderChangeArgs);
                }
            }
       
    
            ....
    	....
    	....
    
        }
    }
    

    One thing worth mentioning here is that when the CurrentViewMode property changes a DataWrapperHelper class is used to set all the cached DataWrapper<T> objects for a particular object into the same state as that just requested. Here is the code that does that.

      // The following functions may be used when dealing with model/viewmodel objects
    // whose entire set of DataWrapper properties are immutable (only have a getter
    // for the property).  They avoid having to do reflection to retrieve the list
    // of wrapper properties every time a mode change, edit state change
    
    /// <summary>
    /// Set all Cinch.DataWrapper properties to have the correct Cinch.DataWrapper.IsEditable 
    /// to the correct state based on the current ViewMode 
    /// </summary>
    /// <param name="wrapperProperties">The properties on which to change the mode</param>
    /// <param name="currentViewMode">The current ViewMode</param>
    public static void SetMode(IEnumerable<DataWrapperBase> wrapperProperties,
        ViewMode currentViewMode)
    {
        bool isEditable = currentViewMode ==
                ViewMode.EditMode || currentViewMode == ViewMode.AddMode;
    
        foreach (var wrapperProperty in wrapperProperties)
        {
            try
            {
                wrapperProperty.IsEditable = isEditable;
            }
            catch (Exception)
            {
                Debug.WriteLine("There was a problem setting the currentViewMode");
            }
        }
    }
    

     

    Validation Rules/IDataErrorInfo Integration

    I recall some time ago Paul Stovell published a great article Delegates and Business Objects which I simply loved, as it seemed to make so much sense to me. To this end Cinch, makes use of pauls great idea to use delegates to provide validation for business objects.

    The idea is simply the business objects has AddRule(Rule newRule) method which is used to add rules, the business object also implements IDataErrorInfo, which is the preferred WPF validation technique. Then what basically happens is that when the IDataErrorInfo.IsValid property is called against a particular business object, all the validation rules (delegates) are checked and a list of broken rules (as dictated by the delegate rules added to the object) are presented as the IDataErrorInfo.Error string.

    I urge you all to read Paul Stovell excellent Delegates and Business Objects article 1st, but basically Cinch makes use of this.

    What Cinch provides is

    • A ValidatingObject base class that can be used which accepts any Rule based class to be added.
    • SimpleRule, a simple delegate rule
    • RegexRule, a regular expression rule
    • Quite nicely only declares the rules once per Type (as they are static fields) which saves on the ammount of memory that is required for business object validation

    Here is an example of how to use these with Cinch where the property is a simple type such as String/Int32 etc etc

        
      public class OrderModel : Cinch.ValidatingObject
        {
    
            private Int32 quantity;
    
            //rules
            private static SimpleRule quantityRule;
    
            public OrderModel()
            {
    
    
                #region Create Validation Rules
    
                quantity.AddRule(quantityRule);
    
                #endregion
            }
    
            static OrderModel()
            {
    
                quantityRule = new SimpleRule("Quantity", "Quantity can not be < 0",
                          (Object domainObject)=>
                          {
                              OrderModel obj = (OrderModel)domainObject;
                              return obj.Quantity <= 0;
                          });
            }
    }
    

    However recall I mentioned a special Cinch class to allow the ViewModel to place a single Model field into edit mode using the Cinch.DataWrapper<T> , well we need to do something ever so slightly different for those, we need to do the following:

    public class OrderModel : Cinch.ValidatingObject
    {
        #region Data
        //Any data item is declared as a Cinch.DataWrapper, to allow the ViewModel
        //to decide what state the data is in, and the View just renders 
        //the data state accordingly
        private Cinch.DataWrapper<Int32> customerId;
        
    
        //rules
        private static SimpleRule quantityRule;    
        #endregion
    
        #region Ctor
        public OrderModel()
        {
    	    //setup DataWrappers prior to setting up rules
    	    ....
    	    ....
    	
                #region Create Validation Rules
    
        		quantity.AddRule(quantityRule);
    
                #endregion
    
    
        }
        
        static OrderModel()
        {
    
            quantityRule = new SimpleRule("DataValue", "Quantity can not be < 0",
                      (Object domainObject)=>
                      {
                          DataWrapper<Int32> obj = (DataWrapper<Int32>)domainObject;
                          return obj.DataValue <= 0;
                      });
        }    
        #endregion
    
        #region Public Properties
    
        static PropertyChangedEventArgs quantityChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.Quantity);
    
        public Cinch.DataWrapper<Int32> Quantity
        {
        	get { return quantity; }
            private set
            {
            	quantity = value;
                NotifyPropertyChanged(quantityChangeArgs);
            }
        }
    	
        #endregion
    }
    
    
    

    We need to declare the validtion rule like this for Cinch.DataWrapper<T> objects as they are not simply properties but are actual classes, so we need to specify the DataValue property of the individual Cinch.DataWrapper<T> object to validate for the rule.

    This also comes into play within the IsValid method you get when you inherit from a Cinch.ValidatingObject object. Lets say you have something like this for a UI Model object.

      using System;
    
    using Cinch;
    using MVVM.DataAccess;
    using System.ComponentModel;
    using System.Collections.Generic;
    
    namespace MVVM.Models
    {
        /// <summary>
        /// Respresents a UI Order Model, which has all the
        /// good stuff like Validation/INotifyPropertyChanged/IEditableObject
        /// which are all ready to use within the base class.
        /// 
        /// This class also makes use of <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see>s. Where the idea is that the ViewModel
        /// is able to control the mode for the data, and as such the View
        /// simply binds to a instance of a <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see> for both its data and its editable state.
        /// Where the View can disable a control based on the 
        /// <see cref="Cinch.DataWrapper">Cinch.DataWrapper</see> editable state.
        /// </summary>
        public class OrderModel : Cinch.ValidatingObject
        {
            #region Data
            //Any data item is declared as a Cinch.DataWrapper, to allow the ViewModel
            //to decide what state the data is in, and the View just renders 
            //the data state accordingly
            private Cinch.DataWrapper<Int32> orderId;
            private Cinch.DataWrapper<Int32> customerId;
            private Cinch.DataWrapper<Int32> productId;
            private Cinch.DataWrapper<Int32> quantity;
            private Cinch.DataWrapper<DateTime> deliveryDate;
            private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
    
            //rules
            private static SimpleRule quantityRule;
    
            #endregion
    
            #region Ctor
            public OrderModel()
            {
                #region Create DataWrappers
    
                OrderId = new DataWrapper<Int32>(this, orderIdChangeArgs);
                CustomerId = new DataWrapper<Int32>(this, customerIdChangeArgs);
                ProductId = new DataWrapper<Int32>(this, productIdChangeArgs);
                Quantity = new DataWrapper<Int32>(this, quantityChangeArgs);
                DeliveryDate = new DataWrapper<DateTime>(this, deliveryDateChangeArgs);
    
                //fetch list of all DataWrappers, so they can be used again later without the
                //need for reflection
                cachedListOfDataWrappers =
                    DataWrapperHelper.GetWrapperProperties<OrderModel>(this);
    
                #endregion
    
                #region Create Validation Rules
    
                quantity.AddRule(quantityRule);
    
                #endregion
    
    
                //I could not be bothered to write a full DateTime picker in
                //WPF, so for the purpose of this demo, DeliveryDate is
                //fixed to DateTime.Now
                DeliveryDate.DataValue = DateTime.Now;
            }
    
            static OrderModel()
            {
    
                quantityRule = new SimpleRule("DataValue", "Quantity can not be < 0",
                          (Object domainObject)=>
                          {
                              DataWrapper<Int32> obj = (DataWrapper<Int32>)domainObject;
                              return obj.DataValue <= 0;
                          });
            }
    
    
            #endregion
    
            #region Public Properties
    
            /// <summary>
            /// OrderId
            /// </summary>
            static PropertyChangedEventArgs orderIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.OrderId);
    
            public Cinch.DataWrapper<Int32> OrderId
            {
                get { return orderId; }
                private set
                {
                    orderId = value;
                    NotifyPropertyChanged(orderIdChangeArgs);
                }
            }
    
            /// <summary>
            /// CustomerId
            /// </summary>
            static PropertyChangedEventArgs customerIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.CustomerId);
    
            public Cinch.DataWrapper<Int32> CustomerId
            {
                get { return customerId; }
                private set
                {
                    customerId = value;
                    NotifyPropertyChanged(customerIdChangeArgs);
                }
            }
    
            /// <summary>
            /// ProductId
            /// </summary>
            static PropertyChangedEventArgs productIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.ProductId);
    
            public Cinch.DataWrapper<Int32> ProductId
            {
                get { return productId; }
                private set
                {
                    productId = value;
                    NotifyPropertyChanged(productIdChangeArgs);
                }
            }
    
            /// <summary>
            /// Quantity
            /// </summary>
            static PropertyChangedEventArgs quantityChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.Quantity);
    
            public Cinch.DataWrapper<Int32> Quantity
            {
                get { return quantity; }
                private set
                {
                    quantity = value;
                    NotifyPropertyChanged(quantityChangeArgs);
                }
            }
    
            /// <summary>
            /// DeliveryDate
            /// </summary>
            static PropertyChangedEventArgs deliveryDateChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.DeliveryDate);
    
            public Cinch.DataWrapper<DateTime> DeliveryDate
            {
                get { return deliveryDate; }
                private set
                {
                    deliveryDate = value;
                    NotifyPropertyChanged(deliveryDateChangeArgs);
                }
            }
    
            /// <summary>
            /// Returns cached collection of DataWrapperBase
            /// </summary>
            public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
            {
                get { return cachedListOfDataWrappers; }
            }
            #endregion
    
            #region Overrides
            /// <summary>
            /// Is the Model Valid
            /// </summary>
            public override bool IsValid
            {
                get
                {
                    //return base.IsValid and use DataWrapperHelper, if you are
                    //using DataWrappers
                    return base.IsValid &&
                        DataWrapperHelper.AllValid(cachedListOfDataWrappers);
    
                }
            }
            #endregion
    
        }
    }
    
    
    

    You would then need to override the IsValid property to look like this, where we come up with a combined IsValid for the entire object based not only on its IsValid but also the IsValid state of any nested Cinch.DataWrapper<T> objects, which is very easy as they also inherit from Cinch.EditableValidatingObject which in turn inherits from Cinch.ValidatingObject, so they already have the IDataErrorInfo implementation, so its not that hard to cope with.

    I know this seems a lot of extra work, but the added benifit of the ViewModel being able to set a Models individual field editability state, and have the View relect this seemlessly via bindings, simply can not be ignored.

    /// <summary>
    /// Override hook which allows us to also put any child 
    /// EditableValidatingObject objects IsValid state into
    /// a combined IsValid state for the whole Model
    /// </summary>
    public override bool IsValid
    {
        get
        {
           //return base.IsValid and use DataWrapperHelper, if you are
           //using DataWrappers
           return base.IsValid &&
              DataWrapperHelper.AllValid(cachedListOfDataWrappers);
        }
    }
    

    Typically the WPF style we would use for a TextBox that needed to supply validation support for IDataErrorInfo would look something like the following, where we use the Validation.HasError property to change the border color of the TextBox when there is a validation error present.

    <Style x:Key="ValidatingTextBox" TargetType="{x:Type TextBoxBase}">
        <Setter Property="SnapsToDevicePixels" Value="True"/>
        <Setter Property="OverridesDefaultStyle" Value="True"/>
    
        <Setter Property="KeyboardNavigation.TabNavigation" Value="None"/>
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
    
        <Setter Property="MinWidth" Value="120"/>
    
        <Setter Property="MinHeight" Value="20"/>
    
        <Setter Property="AllowDrop" Value="true"/>
        <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
    
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBoxBase}">
                    <Border 
                          Name="Border"
                          CornerRadius="5" 
                          Padding="2"
    
                          Background="White"
                          BorderBrush="Black"
                          BorderThickness="2" >
                        <ScrollViewer Margin="0" x:Name="PART_ContentHost"/>
    
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="False">
                            <Setter TargetName="Border" Property="Background" Value="LightGray"/>
    
                            <Setter TargetName="Border" Property="BorderBrush" Value="Black"/>
                            <Setter Property="Foreground" Value="Gray"/>
    
                        </Trigger>
                        <Trigger Property="Validation.HasError" Value="true">
                            <Setter TargetName="Border" Property="BorderBrush" 
                                    Value="Red"/>
    
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
    
            <Trigger Property="Validation.HasError" Value="true">
                <Setter Property="ToolTip"
                            Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                            Path=(Validation.Errors).CurrentItem.ErrorContent}"/>
    
            </Trigger>
    
        </Style.Triggers>
    </Style>
    

     

    IEditableObject Support

    I have in the past used a pattern called Memento which basically is a cool pattern for support of Undo on business objects. Basically what it allowed for what the storage of an objects state to a Memento backing object which had the exact same properties, as the business object it was storing state for. So when you started an edit on a business objecvt, you store the current state in a Memento and did your edit. If you cancelled the edit, the business objects state would be restored from the Memento. This does work very well, but Microsoft also support this via an interface called IEditableObject which looks like this:

    • BeginEdit()
    • CancelEdit()
    • EndEdit()

    So using this interface we can actually make our business object store their own state. Now I can take no credit for this next piece of code, it comes from Mark Smith excellent work. Actually a fair amount of Cinch is down to Mark Smiths work, again I did ask Mark if I could poach his code, he said yes, great cheers Mark.

    What Cinch does is provide a base class that can be used for you to inherit from for your business objects, this base class also supports validation via the IDataErrorInfo interface we just discussed above. Here is how it works, On BeginEdit() a little bit of Reflection/LINQ is used to store the current objects state in an internal Dictionary. On Canceldit() the internal Dictionary values are restored to the current objects properties, using the property name as a key into the stored Dictionary state.

    This diagram shows this

    Here is the Cinch base class that does all this.

      using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.ComponentModel;
    using System.Reflection;
    using System.Diagnostics;
    
    namespace Cinch
    {
        /// <summary>
        /// Provides a IDataErrorInfo validating object that is also
        /// editable by implementing the IEditableObject interface
        /// </summary>
        public abstract partial class EditableValidatingObject :
            ValidatingObject, IEditableObject
        {
            #region Data
            /// <summary>
            /// This stores the current "copy" of the object. 
            /// If it is non-null, then we are in the middle of an 
            /// editable operation.
            /// </summary>
            private Dictionary<string, object> _savedState;
            #endregion
    
            #region Public/Protected Methods
            /// <summary>
            /// Begins an edit on an object.
            /// </summary>
    
            public void BeginEdit()
            {
                OnBeginEdit();
                _savedState = GetFieldValues();
            }
    
            /// <summary>
            /// Interception point for derived logic to do work when beginning edit.
            /// </summary>
            protected virtual void OnBeginEdit()
            {
            }
    
            /// <summary>
            /// Discards changes since the last 
            /// <see cref="M:System.ComponentModel.IEditableObject.BeginEdit"/> call.
            /// </summary>
            public void CancelEdit()
            {
                OnCancelEdit();
                RestoreFieldValues(_savedState);
                _savedState = null;
            }
    
            /// <summary>
            /// This is called in response CancelEdit and provides an interception point.
            /// </summary>
            protected virtual void OnCancelEdit()
            {
            }
    
            /// <summary>
            /// Pushes changes since the last 
            /// <see cref="M:System.ComponentModel.IEditableObject.BeginEdit"/> 
            /// or <see cref="M:System.ComponentModel.IBindingList.AddNew"/> 
            /// call into the underlying object.
            /// </summary>
            public void EndEdit()
            {
                OnEndEdit();
                _savedState = null;
            }
    
            /// <summary>
            /// This is called in response EndEdit and provides an interception point.
            /// </summary>
            protected virtual void OnEndEdit()
            {
            }
    
            /// <summary>
            /// This is used to clone the object.  
            /// Override the method to provide a more efficient clone.  
            /// The default implementation simply reflects across 
            /// the object copying every field.
            /// </summary>
            /// <returns>Clone of current object</returns>
            protected virtual Dictionary<string, object> GetFieldValues()
            {
    			return GetType().GetProperties(BindingFlags.Public |
    				BindingFlags.NonPublic | BindingFlags.Instance)
    				.Where(pi => pi.CanRead && pi.GetIndexParameters().Length == 0)
    				.Select(pi => new { Key = pi.Name, Value = pi.GetValue(this, null) })
    				.ToDictionary(k => k.Key, k => k.Value);
    
            }
    
            /// <summary>
            /// This restores the state of the current object from the passed clone object.
            /// </summary>
            /// <param name="fieldValues">Object to restore state from</param>
            protected virtual void RestoreFieldValues(Dictionary<string, object> fieldValues)
            {
    			foreach (PropertyInfo pi in GetType().GetProperties(
    				BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
    				.Where(pi => pi.CanWrite && pi.GetIndexParameters().Length == 0) )
    			{
    				object value;
    				if (fieldValues.TryGetValue(pi.Name, out value))
    					pi.SetValue(this, value, null);
    				else
    				{
    					Debug.WriteLine("Failed to restore property " +
    					pi.Name + " from cloned values, property not found in Dictionary.");
    				}
    			}
            }
            #endregion
        }
    }
    

    So ALL you have to do to get editability support is inherit your UI model objects from Cinch.EditableValidatingObject. Job done.

    So lets see how you might put an object that inherits from Cinch.EditableValidatingObject, into Edit mode.

    Well from the ViewModel we can simply do this.CurrentCustomer.BeginEdit() its that easy. However what you MUST also do if you have any nested Cinch.DataWrapper<T> objects is make sure they to are put into the correct state. You would do this in your UI Model class as follows, where we simple override the protected virtual void OnBeginEdit() we get from inheriting from Cinch.EditableValidatingObject

    Where we may have a UI Model object that looks like

      using System;
    
    using Cinch;
    using MVVM.DataAccess;
    using System.ComponentModel;
    using System.Collections.Generic;
    
    namespace MVVM.Models
    {
        /// <summary>
        /// Respresents a UI Order Model, which has all the
        /// good stuff like Validation/INotifyPropertyChanged/IEditableObject
        /// which are all ready to use within the base class.
        /// 
        /// This class also makes use of <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see>s. Where the idea is that the ViewModel
        /// is able to control the mode for the data, and as such the View
        /// simply binds to a instance of a <see cref="Cinch.DataWrapper">
        /// Cinch.DataWrapper</see> for both its data and its editable state.
        /// Where the View can disable a control based on the 
        /// <see cref="Cinch.DataWrapper">Cinch.DataWrapper</see> editable state.
        /// </summary>
        public class OrderModel : Cinch.EditableValidatingObject
        {
            #region Data
            //Any data item is declared as a Cinch.DataWrapper, to allow the ViewModel
            //to decide what state the data is in, and the View just renders 
            //the data state accordingly
            private Cinch.DataWrapper<Int32> orderId;
            private Cinch.DataWrapper<Int32> customerId;
            private Cinch.DataWrapper<Int32> productId;
            private Cinch.DataWrapper<Int32> quantity;
            private Cinch.DataWrapper<DateTime> deliveryDate;
            private IEnumerable<DataWrapperBase> cachedListOfDataWrappers;
    
            //rules
            private static SimpleRule quantityRule;
    
            #endregion
    
            #region Ctor
            public OrderModel()
            {
                #region Create DataWrappers
    
                OrderId = new DataWrapper<Int32>(this, orderIdChangeArgs);
                CustomerId = new DataWrapper<Int32>(this, customerIdChangeArgs);
                ProductId = new DataWrapper<Int32>(this, productIdChangeArgs);
                Quantity = new DataWrapper<Int32>(this, quantityChangeArgs);
                DeliveryDate = new DataWrapper<DateTime>(this, deliveryDateChangeArgs);
    
                //fetch list of all DataWrappers, so they can be used again later without the
                //need for reflection
                cachedListOfDataWrappers =
                    DataWrapperHelper.GetWrapperProperties<OrderModel>(this);
    
                #endregion
    
                #region Create Validation Rules
    
                quantity.AddRule(quantityRule);
    
                #endregion
    
    
                //I could not be bothered to write a full DateTime picker in
                //WPF, so for the purpose of this demo, DeliveryDate is
                //fixed to DateTime.Now
                DeliveryDate.DataValue = DateTime.Now;
            }
    
            static OrderModel()
            {
    
                quantityRule = new SimpleRule("DataValue", "Quantity can not be < 0",
                          (Object domainObject)=>
                          {
                              DataWrapper<Int32> obj = (DataWrapper<Int32>)domainObject;
                              return obj.DataValue <= 0;
                          });
            }
    
    
            #endregion
    
            #region Public Properties
    
            /// <summary>
            /// OrderId
            /// </summary>
            static PropertyChangedEventArgs orderIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.OrderId);
    
            public Cinch.DataWrapper<Int32> OrderId
            {
                get { return orderId; }
                private set
                {
                    orderId = value;
                    NotifyPropertyChanged(orderIdChangeArgs);
                }
            }
    
            /// <summary>
            /// CustomerId
            /// </summary>
            static PropertyChangedEventArgs customerIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.CustomerId);
    
            public Cinch.DataWrapper<Int32> CustomerId
            {
                get { return customerId; }
                private set
                {
                    customerId = value;
                    NotifyPropertyChanged(customerIdChangeArgs);
                }
            }
    
            /// <summary>
            /// ProductId
            /// </summary>
            static PropertyChangedEventArgs productIdChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.ProductId);
    
            public Cinch.DataWrapper<Int32> ProductId
            {
                get { return productId; }
                private set
                {
                    productId = value;
                    NotifyPropertyChanged(productIdChangeArgs);
                }
            }
    
            /// <summary>
            /// Quantity
            /// </summary>
            static PropertyChangedEventArgs quantityChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.Quantity);
    
            public Cinch.DataWrapper<Int32> Quantity
            {
                get { return quantity; }
                private set
                {
                    quantity = value;
                    NotifyPropertyChanged(quantityChangeArgs);
                }
            }
    
            /// <summary>
            /// DeliveryDate
            /// </summary>
            static PropertyChangedEventArgs deliveryDateChangeArgs =
                ObservableHelper.CreateArgs<OrderModel>(x => x.DeliveryDate);
    
            public Cinch.DataWrapper<DateTime> DeliveryDate
            {
                get { return deliveryDate; }
                private set
                {
                    deliveryDate = value;
                    NotifyPropertyChanged(deliveryDateChangeArgs);
                }
            }
    
            /// <summary>
            /// Returns cached collection of DataWrapperBase
            /// </summary>
            public IEnumerable<DataWrapperBase> CachedListOfDataWrappers
            {
                get { return cachedListOfDataWrappers; }
            }
            #endregion
    
            #region Overrides
            /// <summary>
            /// Is the Model Valid
            /// </summary>
            public override bool IsValid
            {
                get
                {
                    //return base.IsValid and use DataWrapperHelper, if you are
                    //using DataWrappers
                    return base.IsValid &&
                        DataWrapperHelper.AllValid(cachedListOfDataWrappers);
    
                }
            }
            #endregion
    
            #region Static Methods
            /// <summary>
            /// Allows Service layer objects to be translated into
            /// UI objects
            /// </summary>
            /// <param name="cust">Service layer object</param>
            /// <returns>UI layer object</returns>
            public static OrderModel OrderToOrderModel(Order order)
            {
                OrderModel orderModel = new OrderModel();
                orderModel.OrderId.DataValue = order.OrderId;
                orderModel.CustomerId.DataValue = order.CustomerId;
                orderModel.Quantity.DataValue = order.Quantity;
                orderModel.ProductId.DataValue = order.ProductId;
                orderModel.DeliveryDate.DataValue = order.DeliveryDate;
                return orderModel;
    
            }
            #endregion
    
            #region EditableValidatingObject overrides
    
            /// <summary>
            /// Override hook which allows us to also put any child 
            /// EditableValidatingObject objects into the BeginEdit state
            /// </summary>
            protected override void OnBeginEdit()
            {
                base.OnBeginEdit();
                //Now walk the list of properties in the OrderModel
                //and call BeginEdit() on all Cinch.DataWrapper<T>s.
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
            }
    
            /// <summary>
            /// Override hook which allows us to also put any child 
            /// EditableValidatingObject objects into the EndEdit state
            /// </summary>
            protected override void OnEndEdit()
            {
                base.OnEndEdit();
                //Now walk the list of properties in the CustomerModel
                //and call CancelEdit() on all Cinch.DataWrapper<T>s.
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
            }
    
            /// <summary>
            /// Override hook which allows us to also put any child 
            /// EditableValidatingObject objects into the CancelEdit state
            /// </summary>
            protected override void OnCancelEdit()
            {
                base.OnCancelEdit();
                //Now walk the list of properties in the CustomerModel
                //and call CancelEdit() on all Cinch.DataWrapper<T>s.
                //we can use the Cinch.DataWrapperHelper class for this
                DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
    
            }
            #endregion
        }
    }
    
    
    

    So what we need to do is override the Cinch.EditableValidatingObject virtual methods as follows:

    #region EditableValidatingObject overrides
    
    /// <summary>
    /// Override hook which allows us to also put any child 
    /// EditableValidatingObject objects into the BeginEdit state
    /// </summary>
    protected override void OnBeginEdit()
    {
        base.OnBeginEdit();
        //Now walk the list of properties in the CustomerModel
        //and call BeginEdit() on all Cinch.DataWrapper<T>s.
        //we can use the Cinch.DataWrapperHelper class for this
        DataWrapperHelper.SetBeginEdit(cachedListOfDataWrappers);
    }
    
    /// <summary>
    /// Override hook which allows us to also put any child 
    /// EditableValidatingObject objects into the EndEdit state
    /// </summary>
    protected override void OnEndEdit()
    {
        base.OnEndEdit();
        //Now walk the list of properties in the CustomerModel
        //and call CancelEdit() on all Cinch.DataWrapper<T>s.
        //we can use the Cinch.DataWrapperHelper class for this
        DataWrapperHelper.SetEndEdit(cachedListOfDataWrappers);
    }
    
    /// <summary>
    /// Override hook which allows us to also put any child 
    /// EditableValidatingObject objects into the CancelEdit state
    /// </summary>
    protected override void OnCancelEdit()
    {
        base.OnCancelEdit();
        //Now walk the list of properties in the CustomerModel
        //and call CancelEdit() on all Cinch.DataWrapper<T>s.
        //we can use the Cinch.DataWrapperHelper class for this
        DataWrapperHelper.SetCancelEdit(cachedListOfDataWrappers);
    
    }
    #endregion
    

    Where the Cinch framework provides a static helper called DataWrapperHelper, which you MUST use to set the correct edit state of the nested DataWrapper<T> objects, you can use these helper methods:

    • DataWrapperHelper.SetBeginEdit(IEnumerable<DataWrapperBase> wrapperProperties)
    • DataWrapperHelper.SetEndEdit(IEnumerable<DataWrapperBase> wrapperProperties)
    • DataWrapperHelper.SetCancelEdit(IEnumerable<DataWrapperBase> wrapperProperties)

    Where the IEnumerable<DataWrapperBase> wrapperProperties is actually the cachedListOfDataWrappers which was obtained during the object construction

    You do not have to worry about this, Cinch will do this for you providing you do the right thing in the UI Model class. If you are feeling a little lost by all this, do not worry one of the subsequent articles will walk through how to create a UI Model using Cinch. This article is more about this Cinch internals for those that may be interested.

    WeakEvent Creation

    Before I start talking about how to create WeakEvents, I think this may be a good place to start a small discussion. I imagine there are loads of readers/.NET developers that think Events in .NET are cool. Well me too, I love events. The thing is, how many of you think you need to worry much about Garbage Collection and when dealing with events, .NET manages its own memory via the GC right? Well yeah it does, but Events are one area that are shall we say a little gray in .NET.

    In the diagram above, there is an object ("eventExposer") that declares an event ("SpecialEvent"). Then, a form is created ("myForm") that adds a handler to the event. The form is closed and the expectation is that the form will be released to garbage collection but it isn't. Unfortunately, the underlying delegate of the event still maintains a strong reference to the form because the form's handler wasn't removed.

    The image and text are borrowed from http://diditwith.net/2007/03/23/SolvingTheProblemWithEventsWeakEventHandlers.aspx

    In typical applications, it is possible that handlers that are attached to event sources will not be destroyed in coordination with the listener object that attached the handler to the source. This situation can lead to memory leaks. Windows Presentation Foundation (WPF) introduces a particular design pattern that can be used to address this issue, by providing a dedicated manager class for particular events and implementing an interface on listeners for that event. This design pattern is known as the WeakEvent pattern.

    MSDN : http://msdn.microsoft.com/en-us/library/aa970850.aspx

    Now if you have ever looked into the Weak Event mananger / interface implementation you will realise it is quite a lot of work and you must have a new WeakEventManager per Event type. This to me sounds like too much work, so I would prefer some other mechanisms, such as have a WeakEvent in the beginning. Better still maybe have a weak listener that only reacts to the source event if the source of the event is still alive and has not been GC'd.

    Raise a WeakEvent<T>

    So without further ado let me show you some handy little helpers that are available within Cinch when dealing with Events, and possibly making them Weak. It is still obvioulsy better to Add/Remove the delegates for an event manually where possible, but sometimes you just do not know the lifecyles of the objects involved, so it is prefferable to opt for a WeakEvent strategy.

    Firstly let's use the absolutely brilliant WeakEvent<T> from the very very talented Daniel Grunwald, who published a superb article on WeakEvents some time ago. Daniels WeakEvent<T>, shows how you can raise an event in a weak manner.

    I am not going to bore you with all the code for WeakEvent<T> but one thing that you should probably get familiar with, if you are not already is the WeakReference class. This is a standard .NET class, which references an object while still allowing that object to be reclaimed by garbage collection.

    Pretty much any WeakEvent subscription/raising of event, will use an internal WeakReference class to allow the source of the event or the subscriber to be GC'd.

    Anyway to use Daniel Grunwalds WeakEvent<T> we can do the following:

    Declaring the WeakEvent<T>

    private readonly WeakEvent<EventHandler<EventArgs>> 
         dependencyChangedEvent =
             new WeakEvent<EventHandler<EventArgs>>();
    
    public event EventHandler<EventArgs> DependencyChanged
    {
      add { dependencyChangedEvent.Add(value); }
      remove { dependencyChangedEvent.Remove(value); }
    }
    
    

    Raising the WeakEvent<T>

    dependencyChangedEvent.Raise(this, new EventArgs());
    

    Listening to WeakEvent<T>

    SourceDependency.DependencyChanged += OnSourceChanged;
    ...
    private void OnSourceChanged(object sender, EventArgs e)
    {
    
    }
    

    So that is how you could make a WeakEvent<T>, but sometimes it is not your own code and you are not in charge of the Events contained in the code. Perhaps you are using a 3rd party control set. So in that case you may need to use a WeakEvent subcription. Cinch provides 2 methods of doing this.

    WeakEvent Subscription

    So above we saw how to raise a WeakEvent using Daniel Grunwalds WeakEvent<T>, so how about in the case where we want to subcribe to an existing event. Again this is typically achieved using a WeakReference class to check the WeakReference.Target for null, if the value is null the source of the event has been garbage collected so do not fire the invocation list delegate, if it is not null the source of the event is alive so call the invocation list delegate which subscribed to the event.

    Cinch provides 2 methods to do this.

    WeakEventProxy

    Which is a neat little class which Paul Stovell wrote some time ago. The entire class looks like this:

    using System;
    
    namespace Cinch
    {
    
        public class WeakEventProxy<TEventArgs> : IDisposable
            where TEventArgs : EventArgs
        {
            #region Data
            private WeakReference callbackReference;
            private readonly object syncRoot = new object();
            #endregion
    
            #region Ctor
            /// <summary>
            /// Initializes a new instance of the <see 
    	      /// cref="WeakEventProxy<TEventArgs>"/> class.
            /// </summary>
    
            /// <param name="callback">The callback.</param>
            public WeakEventProxy(EventHandler<TEventArgs> callback)
            {
                callbackReference = new WeakReference(callback, true);
            }
            #endregion
    
            #region Public Methods
            /// <summary>
            /// Used as the event handler which should be subscribed to source collections.
            /// </summary>
    
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void Handler(object sender, TEventArgs e)
            {
                //acquire callback, if any
                EventHandler<TEventArgs> callback;
                lock (syncRoot)
                {
                    callback = callbackReference == null ? null : 
    			callbackReference.Target as EventHandler<TEventArgs>;
                }
    
                if (callback != null)
                {
                    callback(sender, e);
                }
            }
    
            /// <summary>
    
            /// Performs application-defined tasks associated with freeing, 
    	      /// releasing, or resetting unmanaged resources.
            /// </summary>
            /// <filterpriority>2</filterpriority>
            public void Dispose()
            {
                lock (syncRoot)
                {
                    GC.SuppressFinalize(this);
    
                    if (callbackReference != null)
                    {
                        //test for null in case the reference was already cleared
                        callbackReference.Target = null;
                    }
    
                    callbackReference = null;
                }
            }
            #endregion
        }
    }

    And to use this we can simply do the following:

    Declare Event Handlers like

    private EventHandler<NotifyCollectionChangedEventArgs> 
         collectionChangeHandler;
    private WeakEventProxy<NotifyCollectionChangedEventArgs> 
         weakCollectionChangeListener;
    

    And Wire Up the Event Subscription Delegate Like this

    if (weakCollectionChangeListener == null)
    {
      collectionChangeHandler = OnCollectionChanged;
      weakCollectionChangeListener = 
         new WeakEventProxy<NotifyCollectionChangedEventArgs>(
             collectionChangeHandler);
    }
    ncc.CollectionChanged += weakCollectionChangeListener.Handler;
    
    
    private void OnCollectionChanged(object sender, 
     NotifyCollectionChangedEventArgs e)
    {
    
    }

    WeakEvent Subscriber With Auto UnSubscription

    I was trawling the internet one day and found this superb article on WeakEvents

    http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx. This links contained some cool code that I have used within Cinch, which not only allows users to create WeakEvent subscriptions, but allows the user to specify an auto unsubscribe callback delegate. In addition using a small variation to this code it is possible to make all subscribed event handlers weak. Lets have a quick look at the syntax for both these operations

    Specifying A WeakEvent Subscription With Unhook

    We simply do this.

    workspace.CloseWorkSpace +=
        new EventHandler<EventArgs>(OnCloseWorkSpace).
           MakeWeak(eh => workspace.CloseWorkSpace -= eh);
           
    private void OnCloseWorkSpace(object sender, EventArgs e)
    {
    
    }
    

    That one line created a Weak listener with an auto unsubscribe. Neat huh

    I mentioned that you can also use this code to create a WeakEvent, such that all subscribers to a particular event would be Weak. This is how you could do that using this code.

    public class EventProvider
    {
        private EventHandler<EventArgs> closeWorkSpace;
        public event EventHandler<EventArgs> CloseWorkSpace
        {
            add
            {
                closeWorkSpace += value.MakeWeak(eh => closeWorkSpace -= eh);
            }
            remove
            {
            }
        }
    }

    As I say I can not take much credit for this code, it came from the link specified, but I do think its very handy. We actually use it in production code without too many issues. The only thing I have noticed is that it doesn't play well with the CollectionChanged of ObservableCollection<T>, but then I just use the WeakEventProxy that I also mentioned above that is part of Cinch, and that works just fine.

     

    Mediator Messaging

    Now I do not know about you, but generally when I work with the MVVM framework, I do not have a single ViewModel managing the whole shooting match. I actually have a number of them (in fact we have loads). One thing that is an issue using the standard MVVM pattern is cross ViewModel communication. After all the ViewModels that form an application may all be disparate unconnected objects that no nothing about each other. However they need to know about certain actions that a user performed. Here is a concrete example.

    Say you have 2 Views one with customers and one with orders for a customer. Lets say the orders view was using a OrdersViewModel and that the customers view was using a CustomersViewModel, and when a Customers order is updated deleted or added to that the Customer view should show some sort of visual trigger to alert the user that some order detail of the customer changed.

    Sounds simple enough right. However we have 2 independant views run by 2 independant ViewModels, with no link, but clearly there needs to be some sort of connection from the OrdersViewModel to the CustomersViewModel, some sort of messaging perhaps.

    This is exactly what the Mediator pattern is all about, it is a simple light weight messaging system. I wrote about this some time ago on my blog, which in turn got made a tonne better by Josh Smith / Marlon Grech (as an atomic pair) who came up with the Mediator implementation you will see in Cinch.

    So how does the Mediator work.

    This diagram may help

    The idea is a simple one, the Mediator listens for incoming messages, sees who is interested in a particular message, and calls each of those that are subscribed against a given message. The messages are usually strings.

    Basically what happens is that there is a single instance of the Mediator sitting somewhere (Usually exposes as a static property on the ViewModelBase class) that is waiting for objects to subscribe to it either using :

    • An entire object reference. Then any Mediator message methods that have been marked up with the MediatorMessageSinkAttribute attribute, will be located on the registered object (using Reflection) and will have a callback delegate automatically created
    • An actual Lambda callback delegate, which will be

    In either case the Mediator maintains a list of WeakActions callback delegates. Where each WeakAction is a delegate which uses an internal WeakReference class to check the WeakReference.Target for null, before calling back the delegate. This caters for the fact that the target of the callback delegate may no longer be alive as it may have been Garbage Collected. Any instances of WeakActions callback delegates that point to objects that are no longer alive are removed from the list of Mediator WeakActions callback delegates.

    When a callback delegate is obtained, either the original callback delegate is called or the Mediator message methods that have been marked up with the MediatorMessageSinkAttribute attribute will be called.

    Here is an example of how to use the Mediator in all the different possible manners.

    Registering For Messages

    Using an explicit callback delegate (this is not my preffered option though)

    We simply create the correct type of delegate and Register a callback for a message notification with the Mediator.

    public delegate void DummyDelegate(Boolean dummy);
    ...
    
    Mediator.Register("AddCustomerMessage", new DummyDelegate((x) =>
    {
        AddCustomerCommand.Execute(null);
    }));
    

    Register an entire object, and use the MediatorMessageSinkAttribute attribute

    This is my favourite approach and is the simplist approach in my opinion. You just need to register an entire object with the Mediator and attribute up some message hook methods.

    So to register, this is done for you in Cinch, so you don't have to do anything. Simply inherit from ViewModelBase, job done. If you are wondering how this is done, the ViewModelBase class in Cinch simply registers itself with the Mediator like this.

    //Register all decorated methods to the Mediator
    Mediator.Register(this);
    

    So any method that is marked up with the MediatorMessageSinkAttribute attribute, will be located on the registered object (using Reflection) and will have a callback delegate automatically created. Here is an example

    /// <summary>
    /// Mediator callback from StartPageViewModel
    /// </summary>
    /// <param name="dummy">Dummy not needed</param>
    
    [MediatorMessageSink("AddCustomerMessage", ParameterType = typeof(Boolean))]
    private void AddCustomerMessageSink(Boolean dummy)
    {
        AddCustomerCommand.Execute(null);
    }
    
    

    So how about notification of messages.

    Message Notification

    That is very easy to do, we simply use the Mediator.NotifyCollegues() method as follows:

    //Use the Mediator to send a Message to MainWindowViewModel to add a new 
    //Workspace item
    Mediator.NotifyColleagues<Boolean>("AddCustomerMessage", true);
    
    
    

    So any objects that subscribed to this message will now be called back by the list of Mediator WeakActions callback delegates.

    What's Coming Up?

    In the subsequent articles I will be showcasing it roughly like this

    1. A walkthrough of Cinch, and it's internals II
    2. How to develop ViewModels using Cinch
    3. How to Unit test ViewModels using Cinch app, including how to test Background work threads which may run within Cinch ViewModels
    4. A Demo app using Cinch

    That's It Hope You Liked It

    That is actually all I wanted to say right now, but I hope from this article you can see where Cinch is going and how it could help you with MVVM. As we continue our journey we will be covering the remaining items within Cinch and then we will move on to show you how to develop an app with Cinch.

    Thanks.

    As always votes / comments are welcome.

     

    History

    • 19/07/2009 : Initial release
    • 25/07/2009 :
      • Altered NumericTextBoxBehavior to take into account pasted data
      • Change INotifyPropertyChanged to used static LINQ expression trees
      •  
    • 02/08/2009 : Change INotifyPropertyChanged to use Phils (a readers) idea which you can read more about here CinchII.aspx?msg=3141144#xx3141144xx
    • 15/08/2009 : Added support for DataWrappers to notify parent when a internal DataWrapper property changes
    • 12/09/2009 : Adding caching suport to DataWrapper and fixed RegExRule
    • 05/12/09 : Added new code sections to show users how to add validation rules using the new validation methods within Cinch
    • 24/12/09 : Updated code snippet for NumericTextBoxBehavior
  • License

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

    About the Author

    Sacha Barber


    Member
    I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

    - MSc (Passed with distinctions), in Information Technology for E-Commerce
    - BSc Hons (1st class) in Computer Science & Artificial Intelligence

    Both of these at Sussex University UK.

    Award(s)

    I am lucky enough to have won a few awards for Zany Crazy code articles over the years

    • Microsoft C# MVP 2010
    • Codeproject MVP 2010
    • Microsoft C# MVP 2009
    • Codeproject MVP 2009
    • Microsoft C# MVP 2008
    • Codeproject MVP 2008
    • And numerous codeproject awards which you can see over at my blog

    Occupation: Software Developer (Senior)
    Location: United Kingdom United Kingdom

    Other popular Windows Presentation Foundation articles:

    Article Top
    You must Sign In to use this message board.
    FAQ FAQ 
     
    Noise Tolerance  Layout  Per page   
     Msgs 1 to 25 of 216 (Total in Forum: 216) (Refresh)FirstPrevNext
    GeneralResource DataTemplate and SimpleCommand binding PinmemberSevententh1:30 4 Feb '10  
    AnswerRe: Resource DataTemplate and SimpleCommand binding PinmemberSevententh1:37 4 Feb '10  
    GeneralRe: Resource DataTemplate and SimpleCommand binding PinmvpSacha Barber1:56 4 Feb '10  
    GeneralSetting Visibility of controls in a view Pinmemberkfrosty6:13 28 Jan '10  
    GeneralRe: Setting Visibility of controls in a view [modified] PinmvpSacha Barber6:26 28 Jan '10  
    GeneralRe: Setting Visibility of controls in a view Pinmemberkfrosty7:00 28 Jan '10  
    GeneralRe: Setting Visibility of controls in a view PinmvpSacha Barber7:18 28 Jan '10  
    GeneralNo Magic Strings Pinmemberivan_ark11:04 22 Jan '10  
    GeneralRe: No Magic Strings PinmvpSacha Barber11:06 22 Jan '10  
    GeneralRe: No Magic Strings [modified] Pinmemberivan_ark11:10 22 Jan '10  
    GeneralRe: No Magic Strings PinmvpSacha Barber22:27 22 Jan '10  
    GeneralRe: No Magic Strings Pinmemberivan_ark14:02 1 Feb '10  
    QuestionError Multiple mouse events on a TreeView PinmemberSevententh5:20 22 Jan '10  
    QuestionDataWrapper IsDirty always returns false Pinmemberguilford5:12 19 Jan '10  
    AnswerRe: DataWrapper IsDirty always returns false PinmvpSacha Barber5:56 19 Jan '10  
    AnswerRe: DataWrapper IsDirty always returns false PinmvpSacha Barber11:50 19 Jan '10  
    GeneralMVVM OpenFileDialog PinmemberSfarz0:12 6 Jan '10  
    GeneralRe: MVVM OpenFileDialog PinmvpSacha Barber0:27 6 Jan '10  
    GeneralFancyButton is broken Pinmembercbordeman14:45 29 Dec '09  
    GeneralRe: FancyButton is broken PinmvpSacha Barber21:22 29 Dec '09  
    GeneralRe: FancyButton is broken Pinmembercbordeman7:03 30 Dec '09  
    GeneralAdding an IsDirty flag to the DataWrapper class PinmemberTPardue10:29 6 Nov '09  
    GeneralRe: Adding an IsDirty flag to the DataWrapper class PinmvpSacha Barber21:45 6 Nov '09  
    GeneralRe: Adding an IsDirty flag to the DataWrapper class PinmvpSacha Barber11:08 11 Nov '09  
    GeneralRe: Adding an IsDirty flag to the DataWrapper class PinmemberTPardue6:27 18 Nov '09  

    General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

    Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads.

    PermaLink | Privacy | Terms of Use
    Last Updated: 23 Dec 2009
    Editor:
    Copyright 2009 by Sacha Barber
    Everything else Copyright © CodeProject, 1999-2010
    Web09 | Advertise on the Code Project