Today is a long awaited day for me. Caliburn is now in official Beta. There have been many bug fixes and a ton of new features since the Alpha release last October. We’ve also been dogfooding it on several projects, one of which is NHProf. I wanted to use this post as an opportunity to summarize Caliburn’s current feature set and introduce you to the Line-Of-Business sample provided with the framework, built with Caliburn and Silverlight.
If you are in the WPF or Silverlight world, you may have spent some time trying to figure out how to cleanly architect a UI with these technologies. You may have come across the MVVM pattern through excellent articles like this one by Josh Smith or you may have found more general UI architecture guidance in Jeremy Miller’s Build Your Own Cab series or on Martin Fowler’s site. Whatever the case, its obvious that building solid UI is difficult and there are a ton of patterns and variations on patterns geared to solving common problems. The goal of Caliburn is to make building UI easier by providing a class library that eliminates the boiler-plate code often involved in implementing these solutions.
Features of the Beta
Actions extend the databinding capabilities of WPF/SL by enabling a UI to bind not only to data but to methods. Caliburn uses triggers to wire events, gestures, and attached events (extensible to any trigger type you can think of) to methods on a presentation-related class. This type of method binding removes much of the glue code involved in building an MVC or MVP architecture. Additionally, it enables very rich Presentation Model (MVVM) scenarios. In addition to basic execution of methods, Caliburn's action mechanism can pass data from the UI into the methods as parameters and bind return values back to the UI (in fact the return behavior of action is entirely extensible by implementing a custom IExecutableResult). A filter mechanism (similar to ASP.NET MVC) exists for decorating methods. Filters can affect the availability of a given action through the UI, which can be represented by automatically disabling, hiding or collapsing controls (extensible to any visualization). There are several built-in filters, but the mechanism is entirely extensible. Caliburn can also automatically execute methods asynchronously, and execute callbacks. It does all the thread marshalling for you.
Caliburn's command implementation is an alternative to WPF's and supplies very useful functionality that is altogether missing from Silverlight. As you might expect, it is an implementation of the Command Pattern. . Commands are built on top of Actions and thus share many of the same features, including multiple input parameters, filters and automatic asynchronous execution. Additionally, commands can be created in hierarchies, such that a parent command can execute multiple child commands. The parent command's availability can also be affected by its children in various ways. There are two types of composite commands available out of the box, but the mechanism is extensible. There is no limit to the depth of the command hierarchy.
MVP and Application Controller
Two common patterns that occur in applications are Supervising Controller and Application Controller. Caliburn supports architectures based on these ideas directly through its various implementations of the IPresenter interface. Often times, these types of architectures involve tricky UI lifecycle issues such as handling activation, deactivation and shutdown semantics for various UI components. The basic logic for handling these scenarios is found in Caliburn’s Presenter, PresenterManager, MultiPresenterManager and Navigator classes. By composing these classes you can create a hierarchical model representing the entire runtime state of your application. In Silverlight, you can even use the browser as an Application Controller with Caliburn’s support for deep linking.
Presentation Model and MVVM
Caliburn also supplies a set of base classes that enable transactional editing, n-level undo/redo, dirty tracking and validation. These classes are perfect for creating an editable ViewModel or representing the “Model” portion of the MVP triad when utilizing a Supervising Controller. This functionality is accomplished through a rich metadata-aware property system, similar to dependency properties, but more suited to the needs of a model rather than a view.
One of the goals of Caliburn is to make it easier to build applications right. To this effect, Caliburn has features geared around unit testing. There is currently rich support for testing databindings in WPF and a simple fluent interface for verifying change notification on model objects. Unit tests for view bindings give the developer the confidence they need to refactor their models, knowing that they will be aware of broken bindings before they run the application. Not only will they be aware that the bindings are broken, but Caliburn’s binding validator will tell you exactly where the problem is in the UI hierarchy and what the specific error was.
Many, many more features…
LOB Sample Application
In addition to the framework, you will find several samples as part of the Beta download. The most thorough demonstration of Caliburn can be found in the Silverlight Contact Manager sample. Some features you can look for are:
- Dependency injection is used throughout.
- Use of Actions throughout (this includes the use of Preview and Dependencies filters).
- The ContactDetailsPresenter.ValidateContact demonstrates the use of a custom IExecutableResult from an Action.
- When you mouse over the 'red dot' after changing a contact, a popup will appear. That is the result of the IExecutableResult.
- IExecutableResult works in conjunction with a custom ValidationResult.
- If you have some invalid properties, you can click on notices in the popup to focus the control related to the error.
- The structure of the application forms a composite hierarchy with implementers of IPresenter. This hierarchy exists at runtime. Below is an example of what might occur:
-> ContactListPresenter (MultiPresenterManager)
-> N of ContactDetailsPresenter (Presenter)
*The red, blue and green outlines show the views bound to the composited presenters.
- The application controller pattern is used as a top level coordinator.
- Deep linking is accomplished with the DeepLinkStateManager.
- The Settings class builds on top of the IsolatedStorageStateManager for simple key/value pairs stored locally.
- The Model classes inherit from ModelBase and uses a special form of property declaration (similar to dependency properties). By nature of this form of definition, these classes gain the following features:
- Transactional editing support (BeginEdit, EndEdit, CancelEdit)
- Property change notification
- Dirty tracking
- N-Level Undo/Redo support
- Advanced shutdown scenarios for presenters.
In addition to Caliburn's framework, this sample demonstrates an application specific framework built on top of Caliburn, to add more convention to the way this app is built. Examples of this include:
- Use of the ViewAttribute in conjunction the ViewZone to detect presenter's views, display them and wire up Action.Target.
- Use of a custom set of attached properties (Bind...) to do some fancy wire up of data binding, validation, etc.
- Use of the HistoryKey/HistoryInfo to aid the DeepLinkStateManager.
Finally, there are a number of other useful SL tidbits built in as well:
- Visual transitions with the TransitionPresenter and implementors of ITransition.
- Modal dialogs
- Data bound tooltips.
- UI scaling (ala ViewBox)
I hope this helps in your overall understanding of Caliburn and serves as an example of UI architecture. Feedback is welcome. Enjoy the new release and have a look at the growing developer documentation!
02-26-2009 9:15 PM