.NET & Funky Fresh

Syndication

News

  • <script type="text/javascript" src="http://ws.amazon.com/widgets/q?ServiceVersion=20070822&amp;MarketPlace=US&amp;ID=V20070822/US/bluspiconinc-20/8001/8b68bf4b-6724-40e7-99a5-a6decf6d8648"> </script>
Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Caliburn Feature Profile

I've just put together a document briefly describing the current set of features that Caliburn supports.  I've added it to the official documentation and copied it below.  If you are new to Caliburn, this should give you a good idea about what we've been up to.  I say "we" because we are now up to three developers!  Christopher Bennage and Michael Pavlovsky are both contributing now and they are going to help me to get a number of loose ends tied up.  We'd love to hear your feedback on existing features as well as requests for new features.  Also, please tell us what your pain points have been in developing with WPF - perhaps Caliburn can find a way to help.

Below is the Caliburn Feature Profile...

Model/View/Presenter and Presentation Model (Model/View/ViewModel) Support

Model/View/Presenter and Presentation Model (aka Model/View/ViewModel) are two of the most appropriate patterns for developing WPF applications due to the rich support for databinding found in the underlying framework.  However, WPF only lets you bind to properties and does not directly support binding to methods, ergo the use of these patterns often requires the creation of tedious boiler plate code.  Caliburn supports MVP and PM by providing a rich set of features on top of WPF databinding through Action Messages.  Action Messages make up for the deficiency in WPF databinding by allowing you to bind to methods.  Below are a list of features that Action Messages enable:

  • Binding directly to methods by using the View.Messages attached property.  Methods can have a variable number of strongly typed parameters.
  • Triggering method invocation by any event, routed event or gesture.
  • Multiple methods can be called based on a single trigger or on an arbitrary number of triggers.
  • Caliburn can automatically determine the default trigger for a given control, so 90% of the time this need not be declared in XAML.
  • Declaring method parameters in XAML that are used to invoke the bound method.  Values can  be explicit or based on standard WPF bindings.
  • Declaring data bindings for return values of bound methods.
  • Allowing Caliburn to automatically determine both method parameters and return value bindings based on method signature and x:Name, thus reducing XAML and keeping markup clean and simple.
  • Executing methods that exist on objects which are properties of the bound presenter.  This is done with a path notation and can bind to N degrees.
  • Routing method invocations up WPF's Visual/Logical tree.  Thus, if the bound presenter does not have the method that is being invoked, Caliburn will route the message up the tree until it finds a presenter which can handle the message.
  • Presenters/Models can be POCO classes.
  • Declarative exception handling for presenters which can be overriden on a method by method basis.  This is done by applying attributes to the presenter or method.
  • Attributes can be added to methods to enable execution conditions.  These are similar to the CanExecute handler of an ICommand, however the methods have strongly typed signatures and their parameters are bound in the same way as standard methods.
  • The interpretation of the execution condition can be decided by the View, through the use of an implementation of ConditionEffect applied with the View.ConditionEffect attached property.  With traditional WPF commands, a failed condition can only disable the UI.  With Caliburn, the view can decided how to interpret this.  Built in effects are Disable, Hide and Collapse, but developers can easily extend this.
  • Automatic asynchronous code execution.  By applying the AsyncAction attribute to a method, Caliburn will run the method on a background thread.  All databinding of parameters and return values works automatically.  Caliburn takes care of marshalling data and events to the appropriate thread.
  • When using AsyncAction, the developer can declare a Callback method.  The return value of the async method can be passed into the callback which will then be automatically run on the UI thread.  Any return value of the callback can be bound to the UI.  Thus the full async pattern that Caliburn supports is as follows:
    • ExecutionCondition is databound from the UI and executed on the UI thread.
    • If ExecutionCondtion returns true, the async action is run on a background thread.
    • If the async action declares a return value with no callback, the return value will be bound to the UI on the proper thread.
    • If the async action declares a callback, it will be called on the UI thread after the async action has completed.  Any return value of the async action will by used as an argument to the Callback.
    • If the callback has a return value, it will be bound to the UI.
    • Any exception that occurs on any thread will be handled by Caliburn and passed to the declared handler, on the UI thread.
  • All ActionMessages triggered by input gestures are modifiable at runtime.  That is, you can let your users change the key bindings fairly effortlessly.

Caliburn uses a variety of techniques under the covers to accomplish these features.  Reflection is used only for discovery.  Unbound delegates are used to safely and efficiently execute actions, therefore the performance issues with reflection-based method invocation are not experienced.  Also, extensive use of weak references, weak dictionaries and weak events are used to help prevent memory leaks.  The code used for unbound delegates, and weak events is a public part of the API, therefore it can be used to handle complex programming scenarios outside Caliburn's scope.

Events

For a more loosely coupled application architecture, you may choose to use an eventing mechanism instead of Action Messages (or you may choose to use a combination of these techniques).  Caliburn supports two different approached to eventing, each suited to different scenarios or styles of programming.

EventBroker

The event broker manages a tree of event topics based on string names.  For example event://Module/Todo/AddNewTodo.  Publishers can declare that their events fire synchronously or asynchronously as well as configure how they route.  For example, the default routing is bubbling, which means that a subscriber registered at event://Module/Todo would receive the event://Module/Todo/AddNewTodo event.  Individual handlers can also specify that they should be run asynchronously.  Below are some features of EventBroker messages:

  • They can be raised through XAML bindings by using EventMessage
  • Events can be raised with any number of parameters and the handlers can have strongly typed arguments to match.
  • The raising of the EventBroker event can be triggered by UI events, routed events, or guestures.
  • Event handlers can define a ExecutionCondition.
  • ExecutionCondition can effect UI availability if wired through XAML. 
  • ConditionEffect can define a UI response to an event which cannot be raised.
  • Application code can be used to manually invalidate an execution condition.
  • Subscribers, publishers and execution conditions can be auto-wired with attributes if you are using a supporting DI container.
  • All key bindings for EventMessages triggered by input gestures are modifiable at runtime.

EventAggregator

The event aggregator serves a similar purpose as event broker but takes a completely different approach.  Rather than using string based event topics, it dispatches to listeners based on strongly typed messages.  To use the same scenario as above, you would have to raise an event by sending an AddNewTodo message instance.  Classes could then subscribe to this event by implementing IListener<AddNewTodo> and registering with EventAggregator.  Below are some additional features of EventAggregator messages:

  • They can be raised through XAML bindings by using EventMessage
  • The raising of the EventAggregator event can be triggered by UI events, routed events, or guestures.
  • Events can be published or handled synchronously or asynchronously.
  • All key bindings for EventMessages triggered by input gestures are modifiable at runtime.

UI Composition and Scope

Often times, when building modular applications, there is a need to build-up a UI in a generic fashion or through a simple API.  The CompositionManager is Caliburn's way of supporting this.  It allows you to declare composition sites within your XAML and to generically interact with them from other parts of the application.  The common scenario is the need to dynamically change out toolbar buttons or menu options depending on the context.  Using Caliburn you would register your menus and toolbars with the CompositionManager and then generically add or remove items at the appropriate times.  Some features supported by Caliburn's composition engine are:

  • Registration of almost any type of element as a composition target.
  • Generic API for changing the components of a composite view.  This also includes turning off the view entirely.
  • Scoping of different composition managers.
  • Simple registration of composites and scopes through attached properties.
  • Looking up scopes by the Presenter or View they apply to.
  • Storing application specific data in scopes.
  • Used as an enabler of lazy-loaded modules.
  • Hierarchical composition.  For example, declare your main menu as a composite and Caliburn can automatically hand you back a composite for any sub-menu item.

Transitions

Caliburn offers a little extra spice through TransitionPresenter and a set of default Transitions.  Transition presenter works just like a ContentControl, but every time you change the Content property, it does so by applying a transition.  Caliburn also has a special control called PresenterHost, which is built on top of TransitionPresenter and further enables the MVP pattern by providing it with the ability to transition between multiple views.  The list of transitions currently supported is:

  • CheckerboardTransition
  • ClothTransition
  • DiagonalWipe
  • DiamondsTransition
  • DoorTransition
  • DotsTransition
  • DoubleRotateWipeTransition
  • ExplosionTransition
  • FadeAndBlurTransition
  • FadeAndGrowTransition
  • FadeTransition
  • FlipTransition
  • HorzontalBlindsTransition
  • HorizontalWipeTransition
  • MeltTransition
  • PageTransition
  • RollTransition
  • RotateTransition
  • RotateWipeTransition
  • VerticalBlindsTransition
  • VeriticalWipe

The mechanism is completely extensible and there are base classes for 2D, 3D and Storyboard based transitions

Modular Deployment

Modular deployment of large applications is very important.  Caliburn has a fully enabled module loading mechanism.  It can both eager and lazy load modules.  Modules can also be given their own child container for service scoping needs.  Below are some features:

  • Completely control modules through the API.
  • Define modules using custom attributes or .module files.
  • Provide custom metadata for your module.
  • Declare the load priority of modules.
  • Allow lazy-loaded modules to inject UI into a shell without loading.
  • Bind ActionMessages to not yet loaded presenters.
  • Bind commands that call into yet to be loaded modules.
  • Lazy module integration with CompositionManager
  • Allow modules to handle their own exceptions when loading.
  • Asynchronous loading of modules.
  • Allow modules to easily register custom services with the container.
  • Customize any part of the module loading mechanism.

Platform Abstractions

If you have a need to unit test a class that makes use of MessageBox, OpenFileDialog or SaveFileDialog you will wind up abstracting an interface and creating some sort of fake implementation.  Caliburn has gone ahead and done the leg work in this case.

State Persistence

Users want their application to remember their settings from session to session.  In order to support this idea, Caliburn has a StateManager.  By using attached properties, you can declare what part of your UI should be tracked for state persistence.  Caliburn offers both binary and xml serialization options.  Both the serialization and the state tracking mechanism are completely customizable.  This enables you to teach Caliburn how to track the important aspects of your app.

Pluggable Services

Every service that Caliburn provides declares an interface and a single concrete, default implementation.  This allows you to replace any of Caliburn's services with your own implementation without affecting the rest of the framework.  Additionally, each default implementation was built with virtual method implementations, so that if you only want to change one aspect of the default service, you can just override the specific method(s) rather then write an entirely new service.

Caliburn also provides fake implementations of each of its services for use in unit testing.

The entire pluggable service mechanism that Caliburn offers is powered by dependency injection.  Caliburn provides adapters to the four main .NET dependency injection containers: Windsor, StructureMap, Spring.net and Unity.  For smaller projects, if a DI container is not desired, Caliburn can use its own simple implementation to power the framework.

Utilities

Caliburn provides a number of simple utilities for improved development experiences:

  • A general abstraction for dependency injection containers.
  • An Element helper class for deserializing Xaml from various sources (string, stream, resource, etc.)
  • A simple DI container implementation for projects that don't need to pull our the "big guns."
  • Some optional simple base classes for views and presenters.
  • An extensible metadata system.
  • Several classes that facilitate advanced memory management issues. ie. WeakDictionary
  • Xaml markup extensions for common tasks:  resolving dependencies, creating gestures, creating messages, etc.
  • Classes that ease the authoring of asynchronous code and make certain commanding scenarios easier.
  • Utilities for creating unbound methods and weak events.
  • A DTO base class that automatically turns all public properties into dependency properties.

Posted 05-27-2008 9:34 AM by Rob Eisenberg

[Advertisement]

Comments

DotNetKicks.com wrote Caliburn Feature Profile
on 05-27-2008 9:36 AM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Caliburn Feature Profile - .NET & Funky Fresh wrote Caliburn Feature Profile - .NET &amp; Funky Fresh
on 05-27-2008 10:17 AM

Pingback from  Caliburn Feature Profile - .NET &amp; Funky Fresh

Ryan Cromwell wrote re: Caliburn Feature Profile
on 05-27-2008 12:06 PM
Awesome stuff Rob.
KShaban wrote re: Caliburn Feature Profile
on 05-27-2008 1:40 PM
Very good work. We'll be starting a project soon using Caliburn!
Nico Clevers wrote re: Caliburn Feature Profile
on 05-28-2008 7:07 AM
I found a link to this site on Silverlight.net. But it is not completly clear to me, if Caliburn supports Silverlight or not. Is that the case? Or are there plans to implement this support? Thx!
Rob Eisenberg wrote re: Caliburn Feature Profile
on 05-28-2008 8:31 AM

@Nico

Currently Caliburn does not support Silverlight.  However, after the release of Silverlight 2 Beta 2 I will begin looking at what parts can be ported.  So, eventually we plan to have a Silverlight version of Caliburn.

Bryan Reynolds wrote re: Caliburn Feature Profile
on 05-29-2008 1:11 AM
Nice!
Christopher Bennage wrote re: Caliburn Feature Profile
on 05-29-2008 9:38 PM
I'd like to know what features users are most interested in. It's a long and growing list, and as we begin to document it in earnest, that information would be helpful for setting priorities? So all you WPF developers, what are you most interested in?
Silverlight Hub » Caliburn Feature Profile wrote Silverlight Hub &raquo; Caliburn Feature Profile
on 05-31-2008 5:29 AM

Pingback from  Silverlight Hub &raquo; Caliburn Feature Profile

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)