现在的位置: 首页 > 综合 > 正文

WPF architecture analyzing

2013年10月29日 ⁄ 综合 ⁄ 共 10540字 ⁄ 字号 评论关闭
文章目录

http://martinfowler.com/eaaDev/PresentationModel.html

view is only responsible for projecting image to screen

presentation model do data syncronization with view, has separated data member and data member same as view.

presentation model has reference to view , it's easy to test view without actual UI involved.

data binding : widget control data ,presentation data

 

My understanding of using presentation model is for separate view roles of dynamic swtich display mode and multiple control(visual element) coordination apart.  we do this logic process between presentation model class and view class, not involve model class ;do the control-ralated action without interaction with view class. 

 

http://blogs.msdn.com/b/johngossman/archive/2005/10/08/478683.aspx

Model/View/ViewModel is a variation of Model/View/Controller (MVC) that is tailored for modern UI development platforms where the View is the responsibility of a designer rather than a classic developer.  The designer is generally a more graphical, artistic focused person, and does less classic coding than a traditional developer..  The design is almost always done in a declarative form like HTML or XAML, and very often using a WYSIWYG tool such as Dreamweaver, Flash or Sparkle.  In short, the UI part of the application is being developed using different tools, languages and by a different person than is the business logic or data backend.  Model/View/ViewModel is thus  a refinement of MVC that evolves it from its Smalltalk origins where the entire application was built using one environment and language, into the very familiar modern environment of Web and now Avalon development.

   

Model/View/ViewModel also relies on one more thing:  a general mechanism for data binding.   More on that later.

The Model is defined as in MVC; it is the data or business logic, completely UI independent, that stores the state and does the processing of the problem domain.  The Model is written in code or is represented by pure data encoded in relational tables or XML. 

 

The View in Model/View/ViewModel consists of the visual elements, the buttons, windows, graphics and more complex controls of a GUI.  It encodes the keyboard shortcuts and the controls themselves manage the interaction with the input devices that is the responsibility of Controller in MVC (what exactly happened to Controller in modern GUI development is a long digression...I tend to think it just faded into the background.  It is still there, but we don't have to think about it as much as we did in 1979).  The View is almost always defined declaratively, very often with a tool.  By the nature of these tools and declarative languages some view state that MVC encodes in its View classes is not easy to represent.  For example, the UI may have multiple modes of interaction such as "view mode" and "edit mode" that change the behavior of the controls or the look of the visuals, but these modes can't always be expressed in XAML (though triggers are a great start).  We will solve this problem later.

 

At this point data binding comes into play.  In simple examples, the View is data bound directly to the Model.  Parts of the Model are simply displayed in the view by one-way data binding.  Other parts of the model can be edited by directly binding controls two-way to the data.  For example, a boolean in the Model can be data bound to a CheckBox, or a string field to a TextBox.

In practice however, only a small subset of application UI can be data bound directly to the Model, especially if the Model is a pre-existing class or data schema over which the application developer has no control.  The Model is very likely to have a data types that cannot be mapped directly to controls.  The UI may want to perform complex operations that must be implemented in code which doesn't make sense in our strict definition of the View but are too specific to be included in the Model (or didn't come with the pre-existing model).  Finally we need a place to put view state such as selection or modes.

 

The ViewModel is responsible for these tasks.  The term means "Model of a View", and can be thought of as abstraction of the view, but it also provides a specialization of the Model that the View can use for data-binding.  In this latter role the ViewModel contains data-transformers that convert Model types into View types, and it contains Commands the View can use to interact with the Model

 

comment:

Some Guy: this is just a terminology mismatch. What John calls a ViewModel would be called a view-controller in Cocoa. Check out the Cocoa Design Patterns Guide p 34(http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDesignPatterns/CocoaDesignPatterns

The controller layer frequently contains many lines of code. To make this quantity of code more manageable, it is sometimes useful to subdivide the controller layer further into “model-controllers” and “view-controllers”.

A model-controller is a controller that concerns itself mostly with the model layer. It “owns” the model; its primary responsibilities are to manage the model and communicate with any view-controller
objects. Action methods that apply to the model as a whole will typically be implemented in a model-controller. The document architecture provides a number of these methods for you; for example, NSDocument automatically handles action methods related to saving files.

A view-controller is a controller that concerns itself mostly with the viewlayer. It “owns” the interface (the views); its primary responsibilities are to manage the interface and communicate with the
model-controller. Action methods concerned with data displayed in a view will typically be
implemented in a view-controller."

 

http://msdn.microsoft.com/zh-cn/magazine/cc785479.aspx

 

图 10 Presentation Model 模式
图 11 Supervising Controller 模式 
 

http://msdn.microsoft.com/en-us/magazine/dd419663.aspx

 

http://www.codeproject.com/KB/WPF/CatelPart3.aspx

 

http://www.orbifold.net/default/?p=550

 

How can I propagate changes across threads? 

  • We do not support collection change notifications across threads.
  • We support property change notifications across threads.

property changed within worker thread, delegate func invoked async or sync in UI thread

 

sync invoked cause UI thread slow response , async should consider multi small changes merge into one delegate invoking, and using lock to ignore previous property change because latest changes happens before previous change's delegete being invoked or dispatched in UI thread.

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

 

DataModel

DataModel is responsible for exposing data in a way that is easily consumable by WPF. All of its public APIs must be called on the UI thread only. It must implement INotifyPropertyChanged and/or INotifyCollectionChanged as appropriate. When data is expensive to fetch, it abstracts away the expensive operations, never blocking the UI thread (that is evil!). It also keeps the data “live” and can be used to combine data from multiple sources. These sorts of classes are fairly straightforward to unit test.

ViewModel

A ViewModel is a model for a view in the application (duh!). It exposes data relevant to the view and exposes the behaviors for the views, usually with Commands. The model is fairly specific to a view in the application, but does not subclass from any WPF classes or make assumptions about the UI that will be bound to it. Since they are separate from the actual UI, these classes are also relatively straightforward to unit test.

View

A View is the actual UI behind a view in the application. The pattern we use is to set the DataContext of a view to its ViewModel. This makes it easy to get to the ViewModel through binding. It also matches the DataTemplate/Data pattern of WPF. Ideally, the view can be implemented purely as Xaml with no code behind. The attached property trick comes in very handy for this.

The lines between DataModels and ViewModels can be blurry. DataModels are often shown in the UI with some DataTemplate, which isn’t really so different than the way we use ViewModels. However, the distinction usually makes sense in practice. I also want to point out that there’s often composition at many layers. ViewModels may compose other ViewModels and DataModels. And, DataModels may be composed of other DataModels.

The ViewModel is a model of the view. That means: You want to DataBind a property from
your DataObject (model) to a property from your ViewObject (view) but you sometimes cannot bind directly to a CLR property of the model (because of converting or calculating). This is when ViewModel comes into play. It propagates the already calculated or converted value from your model, so you can bind this property directly to the view property.

The main thrust of the Model/View/ViewModel architecture seems to be that on top of the data (“the Model”), there’s another layer of non-visual components (“the ViewModel”) that map the concepts of the data more closely to the concepts of the view of the data (“the View”). It’s the ViewModel that the View binds to, not the Model directly.

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;
[csharp]
private DispatcherTimer _timer;
timer = new DispatcherTimer(DispatcherPriority.Background);
timer.Interval = TimeSpan.FromMinutes(5);
timer.Tick += delegate { ScheduleUpdate(); };
timer.Start();

[/csharp]
the timer is injected implicitly in the thread associated to the dispatcher of the UI.

抱歉!评论已关闭.