Introduction
Since XAML things have become a bit complicated in trying to conceptualize MVC architectures for Windows applications. The gap between web and win is narrowing and the whole WPF thing adds diverse possibilities to one's toobox. What to use? Model-view-controler, the model-view-presenter or the new paradigm called model-view-viewmodel? I have tried to understand what it's all about and this is what I found out.What's the problem?
WPF has changed a few things:- through declarative programming (i.e. XAML) a lot of plumbing is created for you which especially in the context of databinding saves a lot of code. Another area is e.g. animations and styling; what previously had to be programmed in C# is now possible inside XAML through triggers or events.
- in the MVC pattern the View is presenting the data from the Model but now XAML does this job and sometimes need things like value converters or the ObservableCollection to update the presentation
- user controls in WPF allow you to define a default generic.xaml style which can be overriden when used inside an application, i.e. styling of existing controls is a new feature which adds flexibility to the presentation of the Model
- XAML allows a wide variety of mechanisms to change things or to react to user actions; through the ICommand that is now defined in the framework, through triggers in XAML, through animations, through event bubbling or tunneling (which is also new)
The MVVM architecture
Overview
The model
Using the INotifyPropertyChanged you can bubble changes up the stack. The reason that public methods should be on the UI thread is because the model could call long running or async stuff which would block the UI, though there are methods to let the UI thread handle property changes from a separate thread. See the doc on the Dispatcher object and the WPF threading model for more on this. Note in this context that you can let things happen in the background by means of the BeginInvoke() method of the Dispatcher and the paramter that specifies the priority. The SystemIdle in particular is interesting to be used when the Dispatcher is not busy. The DataModel you can find in the download is mimiced from the Dan Crevier's sample and can serve as an abstract base class for your own models.Dispatcher things
The DispatcherTimer is reevaluated at the top of every Dispatcher loop. Timers are not guaranteed to execute exactly when the time interval occurs, but are guaranteed to not execute before the time interval occurs. This is because DispatcherTimer operations are placed on the Dispatcher queue like other operations. When the DispatcherTimer operation executes is dependent on the other jobs in the queue and their priorities. If a System.Timers.Timer is used in a WPF application, it is worth noting that the System.Timers.Timer runs on a different thread then the user interface (UI) thread. In order to access objects on the user interface (UI) thread, it is necessary to post the operation onto the Dispatcher of the user interface (UI) thread using Invoke or BeginInvoke. For an example of using a System.Timers.Timer, see the Disable Command Source Via System Timer sample. Reasons for using a DispatcherTimer opposed to a System.Timers.Timer are that the DispatcherTimer runs on the same thread as the Dispatcher and a DispatcherPriority can be set on the DispatcherTimer. A DispatcherTimer will keep an object alive whenever the object's methods are bound to the timer. So, the right way to schedule things inside the WPF UI is something like;1 2 3 4 5 | private DispatcherTimer _timer; timer = new DispatcherTimer(DispatcherPriority.Background); timer.Interval = TimeSpan.FromMinutes(5); timer.Tick += delegate { ScheduleUpdate(); }; timer.Start(); |
References
- http://blogs.sqlxml.org/bryantlikes/archive/2006/09/27/WPF-Patterns.aspx
- http://blogs.msdn.com/johngossman/default.aspx
- http://blogs.msdn.com/johngossman/archive/2005/10/08/478683.aspx
- http://questmaster.net/blogs/dirks_blog/archive/2005/10/11/237.aspx
- Threading issues and WPF data binding is well explained in this post of Beatriz Costa