Thursday, June 5, 2008

WPF Composite Application with Caliburn - Part Two

In the first part, we learned how to create a basic composite UI with Cliburn Framework. In this part we'll see how Presenters play their part and how we do binding, etc.


Views and Presenters

Before start working with our Presenters and Views, we need to introduce them to Caliburn. We could do this in IoC container configuration file, or via code (that's what we do here). As for Windsor, we need to create a Facility which is automatically loaded when the assembliy gets loaded, and their Init method is called, so providing type information for our Views as well as our Presenters in Init method seems good enough :



Let's start with "Customer List View". Simply, We need to create a view to show list of our customers. For views, you could use a WPF UserControl. To keep things simple, we'll use a ListBox to show list of our customers :



Notice how the binding information on the view will automatically be bound to public properties of the Presenter. For the Presenter, we can just create a plain class. All the logic behind the UI (Binding Information, Methods, Events, etc) should go into this class. Also, notice how we bind the Presenter to a View via an Attribute :



Just a couple of step before we can show our customers list. At this point, you may ask yourself, How do we Show the form containing customers list when the "View Customer List" button is clicked? How do we let two separate parts of the application talk to each other? How do we bind methods to actions of the UIElements?


Hosting Presenters

To show views in our application, we've had a TabControl in our application's Shell. Let's enhance it a little bit to host our Presenters in a Tabbed-MDI style. To do this, we bind the ItemSource property of our TabControl to a public property of the shell's presenter, so if a new presenter is added to the shell, it will be displayed in the view :



and the Presenter now has a public bindable property :



Yet, we need a way to add an instance of our Presenter (CustomerListPresenter for now) to the Shell's public property. Since two presenters are completely separated, we can benefit from Event Aggregator pattern here, which is implemented by Caliburn Framework. To put it simply, it is an infrastructure to faciliate the Publishing / Subscription of events in your application.

To make this work, we'll create new presenter for our Customer UIElement (to respond to "View Customer List" click), create an event in there, and subscribe to it in ShellPresenter. Later, when the "View Customer List" button is clicked, the event will fire up and go all the way to ShellPresenter. (sounds like regular events?).



...and in Shell Presenter, we've subscribed to the same event :




Messaging

For the last piece of the puzzle, we need to bind the Click event of our button to the public event we have on the Presenter. How do we do this? Caliburn provides us a mechanism known as "Messages". Actually, there are two types of Messages :

  • Action Messages : The one we're focusing here. Action messages will call a method on the Presenter and optionally, bind the data back to the UI.

  • Event Messages : Let's us to create event publication on our View, in markup language (xaml), and later subscribe to those events in other Presenters. (more on this later)
So, in case of Action Message, we can declare one on our "View Customer List" button as simply as :



You may think, how does messaging facility determines the event that should invoke our method? Caliburn has a built-in mapping for element's default event, e.g. Default Event of Button is mapped to Click event, so when we've adding a message to the button, Caliburn knows that is should be invoked on the click event of the button. This might sound trivial, but you should consider it, specially if you're using 3rd party controls or custom controls that Caliburn knows nothing about.

Byt now, you should be able to run the application, and by clicking the "View Customer List" button, our view should open nicely :




Download the project file of the part two here.
Submit this story to DotNetKicks Shout it

7 comments:

jim said...

Many Thanks!
Nice article.

endquote said...

An introduction to Windsor would make this tutorial easier to follow. I'm not familiar with it, and the "getting started" section of their site isn't really together yet.

Hadi Eskandari said...

There is a very good article on MSDN, by Oren Eini, about Inversion Of Control (IoC) and how to use it with Windsor. Hope it helps. The address is : http://msdn.microsoft.com/en-us/library/aa973811.aspx

Anonymous said...

Great article.

One thing though that is driving me crazy and don't know why it's happening.

Every time you select another tabitem, the listbox loses the currently selected index in all tabs.

This is more specially noticeable if you replace Listbox with a ComboBox.

I would love to hear why this is happening and what to do about it.

Free Ebook said...

good post, Thanks for script about SeeSharp: WPF Composite Application with Caliburn

bbv said...

Hi,

links are down?

Taz said...

links are down!! and no pictures in the site :( and this is the only tut for this subject. we need them :)