Tag: Design patterns

  • How many chances…?

    How many chances do you give a new piece of software before moving away? That probably depends on the type of “chances” you are giving.

    If you are irritated by a new UI, then you can probably live with it? If the application crashes and you lose all your work, then you’ll be less forgiving.

    Why do I ask this? I just started using Expression Design – in an attempt to do the right thing, and use the tools that are provided as part of our MSDN and partnership packs.

    Firstly I couldn’t get the tool to do what I wanted with Gradients and fills. I can get over that, as I’m probably using the tool in the wrong way.

    But then it crashed. Doing something simple. And it didn’t save my work. And I lost it all.

    Expression Design – you had your chance and you blew it. Come see me again in a few years and we’ll talk. In the meantime, I’m going back to see my old friend – Fireworks.

  • Silverlight 2: Nested user controls, data-binding and property change notification.

    The Problem:

    The parent form is in charge. This form has a view-model which has all the relevant information loaded, know which other views have been implemented, what data those view need and how and when to display and update those views. This is the master page.

    Within that page you can add user controls. These controls are discreet and reusable. They know about themselves, and any controls nested within. The values within these controls are bound to properties in a backing store (the view-model). This control does not know about it’s parent, it will just generate a notification event when the property changes. The parent must be enabled to process this event.

    A Solution:

    Start with your child control. These should function irrespective of where they are called from. For example a reusable data-grid control. In our situation, this control not only displays a collection of objects, it also dynamically sets the displayed fields in the data-grid, based on a collection of field definitions. This control has a view-model (to which the UI controls are data-bound). It also has dependency properties (which can be set by a parent class) and notification properties (which can notify the parent class of changed properties).So the ViewModel would be coded as follows:

      1:     /// 
      2:     /// Backing class for the data used within the UserControl_View
      3:     /// 
      4:     public class UserControl_ViewModel : ViewModelBase
      5:     {
      6: 
      7:         private ObservableCollection<object> _objectList;
      8:         public ObservableCollection<object> ObjectList
      9:         {
     10:             get { return _objectList;}
     11:             set
     12:             {
     13:                 _objectList = value;
     14:                 _OnPropertyChanged("ObjectList");
     15:             }
     16:         }
     17: 
     18:         private object _selectedObject;
     19:         public object SelectedObject
     20:         {
     21:             get { return _selectedObject;}
     22:             set
     23:             {
     24:                 _selectedObject;= value;
     25:                 _OnPropertyChanged("SelectedObject");
     26:             }
     27:         }
     28: 
     29:     }

    (where the ViewModelBase class takes care of the notification property interface).

    Within the UserControl_View we implement the INotifyPropertyChanged interface again, add an instance of the ViewModel class, and bind to it (We also set an event handler into the View to process the properties being changed in the ViewModel and pass these back into the respective UI dependency properties):

      1:     public partial class UserControl_View : UserControl, INotifyPropertyChanged
      2:     {
      3:         public UserControl_ViewModel ViewModel = new UserControl_ViewModel();
      4: 
      5:         public UserControl_View()
      6:         {
      7:             InitializeComponent();
      8:             this.DataContext = ViewModel;
      9: 
     10:             ViewModel.PropertyChanged += new PropertyChangedEventHandler(ViewModel_PropertyChanged);
     11:         }
     12: 
     13: 
     14:         public event PropertyChangedEventHandler PropertyChanged;
     15:         protected virtual void OnPropertyChanged(string propertyName)
     16:         {
     17:             PropertyChangedEventHandler pceh = PropertyChanged;
     18:             if (pceh != null)
     19:             {
     20:                 pceh(this, new PropertyChangedEventArgs(propertyName));
     21:             }
     22:         }
     23:     
     24:         ...
     25:     }

    The event handler for the ViewModel property changed event is as follows:

      1:         /// Watch for the property changed events in teh view model, and get the values
      2:         void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
      3:         {
      4:             if (e!=null)
      5:             {
      6:                 if (e.PropertyName == "SelectedObject")
      7:                 {
      8:                     SelectedObject = ((UserControl_ViewModel)sender).SelectedObject ;
      9:                     OnPropertyChanged("SelectedObject");
     10:                 }
     11:             }
     12:         }

    This will respond to property notification from the ViewModel, check the name of the property, set the respective dependency property on the VIew, and then raise a property notification event for the View (back to the parent).

    We then add dependency properties to the View to handle the objects being passed into the View, for example:

      1:         public ObservableCollection<object> ObjectCollection
      2:         {
      3:             get { return (ObservableCollection<object>)GetValue(ObjectCollectionProperty); }
      4:             set { SetValue(ObjectCollectionProperty, value); }
      5:         }
      6: 
      7:         /// 
      8:         /// Registration of a property container to hold the collection of objects.
      9:         /// 
     10:         /// This HAS to be a dependency property for parent controls to access this.
     11:         public static readonly DependencyProperty ObjectCollectionProperty =
     12:             DependencyProperty.Register("ObjectCollection",
     13:             typeof(ObservableCollection<object>),
     14:             typeof(UserControl_View),
     15:             new PropertyMetadata(new PropertyChangedCallback(ObjectCollectionChanged)));
     16: 
     17:         /// this method is called from the static DependencyProperty "ObjectCollectionProperty"
     18:         /// by the 4th argument as the PropertyMetadata callback value.
     19:         /// This sets the items in the datagrid
     20:         public static void ObjectCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
     21:         {
     22:             CaseDataGrid instance = d as CaseDataGrid;
     23:             if (instance != null)
     24:             {
     25:                 if (args.NewValue != null)
     26:                 {
     27:                     instance.ViewModel.ObjectCollection = args.NewValue as ObservableCollection<object> ;
     28:                 }
     29:             }
     30:         }

    Once all the DP’s for the View have been added you are complete with the control. Next you will look at the middle layer.

    Conceptually the middle layer works in exactly the same way as the child layer.

    • A ViewModel is used to maintain and bind data.
    • Notification properties are used from the ViewModel to the View
    • Notification properties are used from the View to any parents.
    • Dependency properties are registered in the view, to accept incoming data from a parent .
    • PropertyChangedCallback methods are used to set the properties on the child controls:

        1:         public static void ObjectCollectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        2:         {
        3:             ChildControl instance = (ChildControl)d;
        4:             if (instance != null)
        5:             {
        6:                 if (args.NewValue != null)
        7:                 {
        8:                     ObservableCollection<object> NewCollection = args.NewValue as ObservableCollection<object>;
        9:                     instance.UserControl_View.ObjectCollection = NewCollection;
       10:                 }
       11:             }
       12:         }

    The Master Control

    Once again the conceptual model is very  similar to the middle layer:

    • A view model is used to manage and bind data.
    • Notification properties are used to pass data from the ViewModel to the View.
    • The Master_View XAML binds the ViewModel properties to the Child Dependency Properties.

    This should work a treat 🙂

  • Design patterns

    An excellent reference for gang of four design patterns: http://www.dofactory.com/Patterns/Patterns.aspx