== Implementing MVVM == Setup the following: * Model: Data models or data structures implemented as classes. * ViewModel: Models of the data as "viewed" or required by the Views. A ViewModel encapsulates a Model and exposes it in a format that the View can use. * View: Data binding to ViewModel, with little "code-behind" to implement. It displays a limited window into the Model (data). === Model === === View Model === //======================================================================== // Class TAppViewModel //======================================================================== public class TAppViewModel : INotifyPropertyChanged { #region Fields, Events, and Properties //------------------------------------------------------------------------ // Fields //------------------------------------------------------------------------ private string m_ApplicationName = "MyApp"; private string m_ApplicationVersion = "5.0"; private string m_ApplicationBuildNumber = "20110310"; private string m_ApplicationDevStage = "Dev"; private int m_Tag = 0; //------------------------------ // Events //------------------------------ public event PropertyChangedEventHandler PropertyChanged; //------------------------------------------------------------------------ // Properties //------------------------------------------------------------------------ public string ApplicationName { get { return m_ApplicationName; } set { m_ApplicationName = value; } } public string ApplicationVersion { get { return m_ApplicationVersion; } set { m_ApplicationVersion = value; } } public string ApplicationBuildNumber { get { return m_ApplicationBuildNumber; } set { m_ApplicationBuildNumber = value; } } ... public TAppViewModel() { } public void SomeWorkToDo() { // Trigger Change if (PropertyChanged != null) { TAppLog.LogMessage("TFittingVM.SetBusyFlag", "PropertyChanged event triggered for: IsDataLoading, IsControlAvailable."); PropertyChanged(this, new PropertyChangedEventArgs("IsDataLoading")); PropertyChanged(this, new PropertyChangedEventArgs("IsControlAvailable")); } } } === Main View === The ''Main View'' should implement an instance of ViewModel as a ObjectDataProvider (in XAML), that we call ''AppViewModel''. ... Alternatively, it can be spelled out as: === User Controls (View) === User Controls in ''Main View'' should implement an ''AppViewModel'' dependency property. For example, in the ''Main View'', user controls instances should be called as: The user control dependency property ''AppViewModel'' would be implemented like this (eg, in user control ''ucUserControlTriangle ''): public class ucUserControlTriangle : UserControl { #region AppViewModel dependency property implementation ///------------------------------- /// App View Model ///------------------------------- // Dependency Property public static readonly DependencyProperty AppViewModelProperty = DependencyProperty.Register( "AppViewModel", typeof(TAppViewModel), typeof(ucUserControlTriangle), new FrameworkPropertyMetadata(new TAppViewModel(), OnAppViewModelPropertyChanged, OnCoerceAppViewModelProperty ), OnValidateAppViewModelProperty ); // .NET Property Wrapper public TAppViewModel AppViewModel { // Important: Do not add any logic to these properties, because they are only // called when you set the property from code. If you set the property from XAML // the SetValue() method is called directly. get { return (TAppViewModel)GetValue(AppViewModelProperty); } set { SetValue(AppViewModelProperty, value); } } ///---------------------------------------------------------------------------------------- /// /// OnPropertyChanged event handler for app view model. /// /// Source control /// Event Arguments ///---------------------------------------------------------------------------------------- private static void OnAppViewModelPropertyChanged( DependencyObject source, DependencyPropertyChangedEventArgs e) { ucWorkshopRegistration control = source as ucWorkshopRegistration; //DateTime time = (DateTime)e.NewValue; // Put some update logic here... control.DataContext = (TAppViewModel)e.NewValue; } ///---------------------------------------------------------------------------------------- /// /// /// /// /// /// ///---------------------------------------------------------------------------------------- private static object OnCoerceAppViewModelProperty(DependencyObject sender, object data) { //if ((DateTime)data > DateTime.Now) //{ // data = DateTime.Now; //} return data; } ///---------------------------------------------------------------------------------------- /// /// /// /// /// ///---------------------------------------------------------------------------------------- private static bool OnValidateAppViewModelProperty(object data) { return data is TAppViewModel; } #endregion ... ///------------------------------- /// Constructor ///------------------------------- public ucUserControlTriangle() { InitializeComponents(); // Set DataContext this.DataContext = AppViewModel; } ... } Set that user control's ''DataContext'' property to ''AppViewModel'' dependency property. ///------------------------------- /// Constructor ///------------------------------- public ucUserControlTriangle() { InitializeComponents(); // Set DataContext to dependency property AppViewModel this.DataContext = AppViewModel; } Add Data Binding to controls inside that user control, taking advantage of ''DataContext'' set to the ''AppViewModel''. For example, a ''DataGrid'' would look like this: ... == Resources == * [[http://wpftutorial.net/MVVM.html|WPF Tutorial: MVVM (Overview)]] * [[http://msdn.microsoft.com/en-us/magazine/dd419663.aspx|MSDN Magazine: WPF Apps With The Model-View-ViewModel Design Pattern, by Josh Smith]] * [[http://www.codeproject.com/KB/WPF/TreeViewWithViewModel.aspx|Simplifying the WPF TreeView by Using the ViewModel Pattern, by Josh Smith]] * [[http://stackoverflow.com/questions/1798600/mvvm-what-is-the-ideal-way-for-usercontrols-to-talk-to-each-other|MVVM: What is the ideal way for usercontrols to talk to each other]] * [[http://lostechies.com/gabrielschenker/2009/05/31/fluent-silverlight-part-1/\|Los Techies: Fluent Silverlight (using MVVM)]] * [[http://msdn.microsoft.com/en-us/library/ms752308.aspx|MSDN: Commanding Overview]] * [[http://msdn.microsoft.com/en-us/magazine/cc785480.aspx|MSDN Magazine: Understanding Routed Events and Commands In WPF, by Brian Noyes]] * [[http://zamjad.wordpress.com/2009/07/13/dependency-property-metadata|Dependency Property Metadata]]