== 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]]