Minggu, 23 Januari 2011

View/ViewModel Interaction - Bindings, Commands and Triggers


It looks like I have a set of posts on ViewModel, aka MVVM, that have organically emerged into a series or story of sorts.





Recently, I blogged about The Case for ViewModel, and another on View/ViewModel Association using Convention and Configuration, and a long while back now, I posted an Introduction to the ViewModel Pattern as I was myself picking up this pattern, which has since become the natural way for me to program client applications. This installment adds to this on-going series. I've alluded to this topic in the past, but it is now time to focus and dedicate a post on the interactions between a view and its view model, i.e. the arrows in the diagram below:


The ViewModel Pattern


I like to present ViewModel as something that is not brand-new, but a simple refactoring of [most of the] code-behind into a separate class so that the logic is decoupled from the user interface. This class simply employs the basic OOP constructs that you might have encountered in CS101 - it encapsulates state and behavior, exposed via properties, methods and events.





As simple as properties, methods and events...


All view models will encapsulate some interesting application state or data, exposed as properties, usually, in an observable form, i.e. properties that raise change notifications. Almost all view models will also expose some operations, ideally exposed as vanilla methods. And finally, some view models will also raise application-specific notifications as events.





Declarative glue...


A view is then responsible for consuming and working against the object model exposed by its view model as it presents information, and collect and react to user input, gestures etc. The data-binding engine in Silverlight makes it natural to bind to the properties in one-way or two-way fashion. Commands (in the UI, not in the view model - will address this below) allow invoking operations, usually in response to some user input or external inputs (eg. a timer or GPS input). Finally triggers allow the view to listen to events and translate view model notifications into user interface actions. All of these serve as glue expressed in XAML via declarative markup.


This is captured in the diagram above. Bindings are fairly straightforward and you've more than likely used them if you've done any Silverlight programming. So I am mostly going to focus on commands and triggers, but first, lets see this pattern in action.





An example application...


Translation Application ScreenshotAs always, an example helps make things concrete. I converted Tim Heuer's translation/text-to-speech application to follow the view model. In doing so I used the latest release of Silverlight.FX - while the ViewModel is an abstract presentation, it is useful to pick up a framework that allows you to quickly get started with your application, rather than build the plumbing from scratch.


On the right is a screen shot of the application. It is also now included as part of a series of sample applications packaged with Silverlight.FX. You can dowload the latest version (v3.5) by visiting the project page. I'll have a Silverlight 4 version that takes advantage of new capabilities, but in the mean time the Silverlight 3 version should continue to work. The sample application here uses v2 of Microsoft Translator API, which now has support for not just translating text, but also converting text to speech for a specific set of languages. You'll need to get an API key and update the web.config in the sample on your end to run the application.


TranslateWindowModel Object Model


The class diagram of the view model highlights the interesting things going on in the view model:


In terms of application state, it exposes the text to be translated, the resulting translated text, the list of languages, and whether the speak operation can be performed. In terms of operations, it provides the ability to perform translation, or to speak (as in produce the audio stream) the translated text. Finally in terms of notifications, it lets its associated view know when that audio stream has been loaded and is available for playing.



[Full post continued here...]

Tidak ada komentar: