<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>.NET &amp; Funky Fresh : MEF, Silverlight, MVVM</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/Silverlight/MVVM/default.aspx</link><description>Tags: MEF, Silverlight, MVVM</description><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Caliburn.Micro Soup to Nuts Part 6d – A “Billy Hollis” Hybrid Shell</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/2010/11/18/caliburn-micro-soup-to-nuts-part-6d-a-billy-hollis-hybrid-shell.aspx</link><pubDate>Thu, 18 Nov 2010 21:36:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:63478</guid><dc:creator>Rob Eisenberg</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/rob_eisenberg/rsscomments.aspx?PostID=63478</wfw:commentRss><comments>http://devlicio.us/blogs/rob_eisenberg/archive/2010/11/18/caliburn-micro-soup-to-nuts-part-6d-a-billy-hollis-hybrid-shell.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/HelloScreensSolution_5F00_567419C1.jpg"&gt;&lt;img height="484" width="246" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/HelloScreensSolution_5F00_thumb_5F00_41F15AF4.jpg" align="right" alt="HelloScreensSolution" border="0" title="HelloScreensSolution" style="background-image:none;border-right-width:0px;margin:0px 6px 6px 0px;padding-left:0px;padding-right:0px;display:inline;float:right;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" /&gt;&lt;/a&gt;Up until now I&amp;rsquo;ve been focusing on fairly simple usage of Screens and Conductors. In this article, I want to show something a bit more sophisticated. This sample is based loosely on the ideas demonstrated by Billy Hollis in &lt;a target="_blank" href="http://www.dnrtv.com/default.aspx?showNum=115"&gt;this well-known DNR TV episode&lt;/a&gt;.&amp;nbsp; Rather than take the time to explain what the UI does, &lt;a target="_blank" href="http://vimeo.com/16975621"&gt;have a look at this short video for a brief visual explanation&lt;/a&gt; (apologies for the audio level).&lt;/p&gt;
&lt;p&gt;Ok, now that you&amp;rsquo;ve seen what it does, let&amp;rsquo;s look at how it&amp;rsquo;s put together. As you can see from the screenshot, I&amp;rsquo;ve chosen to organize the project by features: Customers, Orders, Settings, etc. In most projects I prefer to do something like this rather than organizing by &amp;ldquo;technical&amp;rdquo; groupings, such as Views and ViewModels. If I have a complex feature, then I might break that down into those areas.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not going to go line-by-line through this sample. It&amp;rsquo;s better if you take the time to look through it and figure out how things work yourself. But, I do want to point out a few interesting implementation details.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ViewModel Composition&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;One of the most important features of Screens and Conductors in Caliburn.Micro is that they are an implementation of &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Composite_pattern"&gt;the Composite Pattern&lt;/a&gt;, making them easy to compose together in different configurations. Generally speaking, composition is one of the most important aspects of object oriented programming and learning how to use it in your presentation tier can yield great benefits. To see how composition plays a role in this particular sample, lets look at two screenshots. The first shows the application with the CustomersWorkspace in view, editing a specific Customer&amp;rsquo;s Address. The second screen is the same, but with its View/ViewModel pairs rotated three-dimensionally, so you can see how the UI is composed.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Editing a Customer&amp;rsquo;s Address&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/Composition_5F00_03F7CA36.png"&gt;&lt;img height="484" width="621" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/Composition_5F00_thumb_5F00_5BE7ABC7.png" alt="Composition" border="0" title="Composition" style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Editing a Customer&amp;rsquo;s Address (3D Breakout)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/Composition_2D00_3d_2D00_01_5F00_54CB0000.png"&gt;&lt;img height="484" width="621" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/Composition_2D00_3d_2D00_01_5F00_thumb_5F00_687A7A45.png" alt="Composition-3d-01" border="0" title="Composition-3d-01" style="background-image:none;border-right-width:0px;padding-left:0px;padding-right:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;padding-top:0px;" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this application, the ShellViewModel is a Conductor&amp;lt;IWorkspace&amp;gt;.Collection.OneActive. It is visually represented by the Window Chrome, Header and bottom Dock. The Dock has buttons, one for each IWorkspace that is being conducted. Clicking on a particular button makes the Shell activate that particular workspace. Since the ShellView has a TransitioningContentControl bound to the ActiveItem, the activated workspace is injected and it&amp;rsquo;s view is shown at that location. In this case, it&amp;rsquo;s the CustomerWorkspaceViewModel that is active.&amp;nbsp; It so happens that the CustomerWorkspaceViewModel inherits from Conductor&amp;lt;CustomerViewModel&amp;gt;.Collection.OneActive. There are two contextual views for this ViewModel (see below). In the screenshot above, we are showing the details view. The details view also has a TransitioningContentControl bound to the CustomerWorkspaceViewModel&amp;rsquo;s ActiveItem, thus causing the current CustomerViewModel to be composed in along with its view. The CustomerViewModel has the ability to show local modal dialogs (they are only modal to that specific custom record, not anything else). This is managed by an instance of DialogConductor, which is a property on CustomerViewModel. The view for the DialogConductor overlays the CustomerView, but is only visible (via a value converter) if the DialogConductor&amp;rsquo;s ActiveItem is not null. In the state depicted above, the DialogConductor&amp;rsquo;s ActiveItem is set to an instance of AddressViewModel, thus the modal dialog is displayed with the AddressView and the underlying CustomerView is disabled. The entire shell framework used in this sample works in this fashion and is entirely extensible simply by implementing IWorkspace. CustomerViewModel and SettingsViewModel are two different implementations of this interface you can dig into.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Multiple Views over the Same ViewModel&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You may not be aware of this, but Caliburn.Micro can display multiple Views over the same ViewModel. This is supported by setting the View.Context attached property on the View/ViewModel&amp;rsquo;s injection site. Here&amp;rsquo;s an example from the default CustomerWorkspaceView:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;clt:TransitioningContentControl cal:View.Context=&amp;quot;{Binding State, Mode=TwoWay}&amp;quot;
                                 cal:View.Model=&amp;quot;{Binding}&amp;quot; 
                                 Style=&amp;#39;{StaticResource specialTransition}&amp;#39;/&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There is a lot of other Xaml surrounding this to form the chrome of the CustomerWorkspaceView, but the content region is the most noteworthy part of the view. Notice that we are binding the View.Context attached property to the State property on the CustomerWorkspaceViewModel. This allows us to dynamically change out views based on the value of that property. Because this is all hosted in the TransitioningContentControl, we get a nice transition whenever the view changes. This technique is used to switch the CustomerWorkspaceViewModel from a &amp;ldquo;Master&amp;rdquo; view, where it displays all open CustomerViewModels, a search UI and a New button, to a &amp;ldquo;Detail&amp;rdquo; view, where it displays the currently activated CustomerViewModel along with it&amp;rsquo;s specific view (composed in). In order for CM to find these contextual views, you need a namespace based on the ViewModel name, minus the words &amp;ldquo;View&amp;rdquo; and &amp;ldquo;Model&amp;rdquo;, with some Views named corresponding to the Context. For example, when the framework looks for the Detail view of Caliburn.Micro.HelloScreens.Customers.CustomersWorkspaceViewModel, it&amp;rsquo;s going to look for Caliburn.Micro.HelloScreens.Customers.CustomersWorkspace.Detail That&amp;rsquo;s the out-of-the-box naming convention. If that doesn&amp;rsquo;t work for you, you can simply customize the ViewLocator.LocateForModelType func.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom IConductor Implementation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Although Caliburn.Micro provides the developer with default implementations of IScreen and IConductor. It&amp;rsquo;s easy to implement your own. In the case of this sample, I needed a dialog manager that could be modal to a specific part of the application without affecting other parts. Normally, the default Conductor&amp;lt;T&amp;gt; would work, but I discovered I needed to fine-tune shutdown sequence, so I implemented my own. Let&amp;rsquo;s take a look at that:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;[Export(typeof(IDialogManager)), PartCreationPolicy(CreationPolicy.NonShared)]
public class DialogConductorViewModel : PropertyChangedBase, IDialogManager, IConductor {
    readonly Func&amp;lt;IMessageBox&amp;gt; createMessageBox;

    [ImportingConstructor]
    public DialogConductorViewModel(Func&amp;lt;IMessageBox&amp;gt; messageBoxFactory) {
        createMessageBox = messageBoxFactory;
    }

    public IScreen ActiveItem { get; private set; }

    public IEnumerable GetConductedItems() {
        return ActiveItem != null ? new[] { ActiveItem } : new object[0];
    }

    public void ActivateItem(object item) {
        ActiveItem = item as IScreen;

        var child = ActiveItem as IChild&amp;lt;IConductor&amp;gt;;
        if(child != null)
            child.Parent = this;

        if(ActiveItem != null)
            ActiveItem.Activate();

        NotifyOfPropertyChange(() =&amp;gt; ActiveItem);
        ActivationProcessed(this, new ActivationProcessedEventArgs { Item = ActiveItem, Success = true });
    }

    public void CloseItem(object item) {
        var guard = item as IGuardClose;
        if(guard != null) {
            guard.CanClose(result =&amp;gt; {
                if(result)
                    CloseActiveItemCore();
            });
        }
        else CloseActiveItemCore();
    }

    object IConductor.ActiveItem {
        get { return ActiveItem; }
        set { ActivateItem(value); }
    }

    public event EventHandler&amp;lt;ActivationProcessedEventArgs&amp;gt; ActivationProcessed = delegate { };

    public void ShowDialog(IScreen dialogModel) {
        ActivateItem(dialogModel);
    }

    public void ShowMessageBox(string message, string title = null, MessageBoxOptions options = MessageBoxOptions.Ok, Action&amp;lt;IMessageBox&amp;gt; callback = null) {
        var box = createMessageBox();

        box.DisplayName = title ?? &amp;quot;Hello Screens&amp;quot;;
        box.Options = options;
        box.Message = message;

        if(callback != null)
            box.Deactivated += delegate { callback(box); };

        ActivateItem(box);
    }

    void CloseActiveItemCore() {
        var oldItem = ActiveItem;
        ActivateItem(null);
        oldItem.Deactivate(true);
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Strictly speaking, I didn&amp;rsquo;t actually need to implement IConductor to make this work (since I&amp;rsquo;m not composing it into anything). But I chose to do this in order to represent the role this class was playing in the system and keep things as architecturally consistent as possible. The implementation itself is pretty straight forward. Mainly, a conductor needs to make sure to Activate/Deactivate its items correctly and to properly update the ActiveItem property. I also created a couple of simple methods for showing dialogs and message boxes which are exposed through the IDialogManager interface. This class is registered as NonShared with MEF so that each portion of the application that wants to display local modals will get its own instance and be able to maintain its own state, as demonstrated with the CustomerViewModel discussed above.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Custom ICloseStrategy&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Possibly one of the coolest features of this sample is how we control application shutdown. Since IShell inherits IGuardClose, in the Bootstrapper we just override DisplayRootView and wire Silverlight&amp;rsquo;s MainWindow.Closing event to call IShell.CanClose:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;protected override void DisplayRootView() {
    base.DisplayRootView();

    if (Application.IsRunningOutOfBrowser) {
        mainWindow = Application.MainWindow;
        mainWindow.Closing += MainWindowClosing;
    }
}

void MainWindowClosing(object sender, ClosingEventArgs e) {
    if (actuallyClosing)
        return;

    e.Cancel = true;

    Execute.OnUIThread(() =&amp;gt; {
        var shell = IoC.Get&amp;lt;IShell&amp;gt;();

        shell.CanClose(result =&amp;gt; {
            if(result) {
                actuallyClosing = true;
                mainWindow.Close();
            }
        });
    });
}&lt;/pre&gt;
&lt;p&gt;The ShellViewModel inherits this functionality through its base class Conductor&amp;lt;IWorkspace&amp;gt;.Collection.OneActive. Since all the built-in conductors have a CloseStrategy, we can create conductor specific mechanisms for shutdown and plug them in easily. Here&amp;rsquo;s how we plug in our custom strategy:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;[Export(typeof(IShell))]
public class ShellViewModel : Conductor&amp;lt;IWorkspace&amp;gt;.Collection.OneActive, IShell
{
    readonly IDialogManager dialogs;

    [ImportingConstructor]
    public ShellViewModel(IDialogManager dialogs, [ImportMany]IEnumerable&amp;lt;IWorkspace&amp;gt; workspaces) {
        this.dialogs = dialogs;
        Items.AddRange(workspaces);
        CloseStrategy = new ApplicationCloseStrategy();
    }

    public IDialogManager Dialogs {
        get { return dialogs; }
    }
}&lt;/pre&gt;
&lt;p&gt;And here&amp;rsquo;s the implementation of that strategy:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;public class ApplicationCloseStrategy : ICloseStrategy&amp;lt;IWorkspace&amp;gt; {
    IEnumerator&amp;lt;IWorkspace&amp;gt; enumerator;
    bool finalResult;
    Action&amp;lt;bool, IEnumerable&amp;lt;IWorkspace&amp;gt;&amp;gt; callback;

    public void Execute(IEnumerable&amp;lt;IWorkspace&amp;gt; toClose, Action&amp;lt;bool, IEnumerable&amp;lt;IWorkspace&amp;gt;&amp;gt; callback) {
        enumerator = toClose.GetEnumerator();
        this.callback = callback;
        finalResult = true;

        Evaluate(finalResult);
    }

    void Evaluate(bool result)
    {
        finalResult = finalResult &amp;amp;&amp;amp; result;

        if (!enumerator.MoveNext() || !result)
            callback(finalResult, new List&amp;lt;IWorkspace&amp;gt;());
        else
        {
            var current = enumerator.Current;
            var conductor = current as IConductor;
            if (conductor != null)
            {
                var tasks = conductor.GetConductedItems()
                    .OfType&amp;lt;IHaveShutdownTask&amp;gt;()
                    .Select(x =&amp;gt; x.GetShutdownTask())
                    .Where(x =&amp;gt; x != null);

                var sequential = new SequentialResult(tasks.GetEnumerator());
                sequential.Completed += (s, e) =&amp;gt; {
                    if(!e.WasCancelled)
                    Evaluate(!e.WasCancelled);
                };
                sequential.Execute(new ActionExecutionContext());
            }
            else Evaluate(true);
        }
    }
}&lt;/pre&gt;
&lt;p&gt;The interesting thing I did here was to reuse the IResult functionality for async shutdown of the application. Here&amp;rsquo;s how the custom strategy uses it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check each IWorkspace to see if it is an IConductor.&lt;/li&gt;
&lt;li&gt;If true, grab all the conducted items which implement the application-specific interface IHaveShutdownTask.&lt;/li&gt;
&lt;li&gt;Retrieve the shutdown task by calling GetShutdownTask. It will return null if there is no task, so filter those out.&lt;/li&gt;
&lt;li&gt;Since the shutdown task is an IResult, pass all of these to a SequentialResult and begin enumeration.&lt;/li&gt;
&lt;li&gt;The IResult can set ResultCompletionEventArgs.WasCanceled to true to cancel the application shutdown.&lt;/li&gt;
&lt;li&gt;Continue through all workspaces until finished or cancellation occurs.&lt;/li&gt;
&lt;li&gt;If all IResults complete successfully, the application will be allowed to close.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The CustomerViewModel and OrderViewModel use this mechanism to display a modal dialog if there is dirty data. But, you could also use this for any number of async tasks. For example, suppose you had some long running process that you wanted to prevent shutdown of the application. This would work quite nicely for that too.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This concludes our short mini-series on Screens and Conductors. I hope I have provided enough theory, documentation and samples to get you going in the right direction. That said, if you don&amp;rsquo;t understand these concepts or don&amp;rsquo;t see the problems in your app that these were intended to solve, then don&amp;rsquo;t use them. Screens/Conductors are best used when you encounter the sorts of engineering difficulties that they were intended for. Simply inheriting willy-nilly from these base classes will likely add unnecessary complexity to your application. As always, use every feature &lt;em&gt;intentionally&lt;/em&gt; to solve a specific problem&amp;hellip;not just because it&amp;rsquo;s there &lt;img src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/wlEmoticon_2D00_smile_5F00_33707BC6.png" alt="Smile" class="wlEmoticon wlEmoticon-smile" style="border-bottom-style:none;border-left-style:none;border-top-style:none;border-right-style:none;" /&gt; If in doubt, avoid Screens/Conductors. When the need arises, you&amp;rsquo;ll know what they are and where to use them.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Next Up: All About Conventions&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=63478" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.06.34.78/Caliburn.Micro.HelloScreens.zip" length="206682" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Xaml/default.aspx">Xaml</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/databinding/default.aspx">databinding</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF_2F00_e/default.aspx">WPF/e</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/RIA/default.aspx">RIA</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Tutorial/default.aspx">Tutorial</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/UI+Architecture/default.aspx">UI Architecture</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn+Micro/default.aspx">Caliburn Micro</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WP7/default.aspx">WP7</category></item><item><title>Caliburn.Micro Soup to Nuts Pt. 5 – IResult and Coroutines</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/2010/08/21/caliburn-micro-soup-to-nuts-part-5-iresult-and-coroutines.aspx</link><pubDate>Sat, 21 Aug 2010 18:31:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:61612</guid><dc:creator>Rob Eisenberg</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/rob_eisenberg/rsscomments.aspx?PostID=61612</wfw:commentRss><comments>http://devlicio.us/blogs/rob_eisenberg/archive/2010/08/21/caliburn-micro-soup-to-nuts-part-5-iresult-and-coroutines.aspx#comments</comments><description>&lt;p&gt;Before our &lt;a target="_blank" href="http://devlicio.us/blogs/rob_eisenberg/archive/2010/08/07/caliburn-micro-soup-to-nuts-pt-4-working-with-windows-phone-7.aspx"&gt;WP7 detour&lt;/a&gt;, we were deep &lt;a target="_blank" href="http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/17/caliburn-micro-soup-to-nuts-pt-3-all-about-actions.aspx"&gt;in the thick of Actions&lt;/a&gt;. I mentioned that there was one more compelling feature of the Actions concept called Coroutines. If you haven&amp;rsquo;t heard that term before, here&amp;rsquo;s what &lt;a target="_blank" href="http://en.wikipedia.org/wiki/Coroutine"&gt;wikipedia&lt;/a&gt;* has to say:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;In &lt;a href="http://en.wikipedia.org/wiki/Computer_science"&gt;computer science&lt;/a&gt;, &lt;strong&gt;coroutines&lt;/strong&gt; are program components that generalize &lt;a href="http://en.wikipedia.org/wiki/Subroutine"&gt;subroutines&lt;/a&gt; to allow multiple entry points for suspending and resuming execution at certain locations. Coroutines are well-suited for implementing more familiar program components such as &lt;a href="http://en.wikipedia.org/wiki/Cooperative_multitasking"&gt;cooperative tasks&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Iterator"&gt;iterators&lt;/a&gt;,&lt;a href="http://en.wikipedia.org/wiki/Lazy_evaluation"&gt;infinite lists&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Pipeline_(software)"&gt;pipes&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here&amp;rsquo;s one way you can thing about it: Imagine being able to execute a method, then pause it&amp;rsquo;s execution on some statement, go do something else, then come back and resume execution where you left off. This technique is extremely powerful in task-based programming, especially when those tasks need to run asynchronously. For example, let&amp;rsquo;s say we have a ViewModel that needs to call a web service asynchronously, then it needs to take the results of that, do some work on it and call another web service asynchronously. Finally, it must then display the result in a modal dialog and respond to the user&amp;rsquo;s dialog selection with another asynchronous task. Accomplishing this with the standard event-driven async model is not a pleasant experience. However, this is a simple task to accomplish by using coroutines. The problem&amp;hellip;C# doesn&amp;rsquo;t implement coroutines natively. Fortunately, we can (sort of) build them on top of iterators.&lt;/p&gt;
&lt;p&gt;There are two things necessary to take advantage of this feature in Caliburn.Micro: First, implement the IResult interface on some class, representing the task you wish to execute; Second, yield instances of IResult from an Action.** Let&amp;rsquo;s make this more concrete. Say we had a Silverlight application where we wanted to dynamically download and show screens not part of the main package. First we would probably want to show a &amp;ldquo;Loading&amp;rdquo; indicator, then asynchronously download the external package, next hide the &amp;ldquo;Loading&amp;rdquo; indicator and finally navigate to a particular screen inside the dynamic module. Here&amp;rsquo;s what the code would look like if your first screen wanted to use coroutines to navigate to a dynamically loaded second screen:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System.Collections.Generic;
using System.ComponentModel.Composition;

[Export(typeof(ScreenOneViewModel))]
public class ScreenOneViewModel
{
    public IEnumerable&amp;lt;IResult&amp;gt; GoForward()
    {
        yield return Loader.Show(&amp;quot;Downloading...&amp;quot;);
        yield return new LoadCatalog(&amp;quot;Caliburn.Micro.Coroutines.External.xap&amp;quot;);
        yield return Loader.Hide();
        yield return new ShowScreen(&amp;quot;ExternalScreen&amp;quot;);
    }
}&lt;/pre&gt;
&lt;p&gt;First, notice that the Action &amp;ldquo;GoForward&amp;rdquo; has a return type of IEnumerable&amp;lt;IResult&amp;gt;. This is critical for using coroutines. The body of the method has four yield statements. Each of these yields is returning an instance of IResult. The first is a result to show the &amp;ldquo;Downloading&amp;rdquo; indicator, the second to download the xap asynchronously, the third to hide the &amp;ldquo;Downloading&amp;rdquo; message and the fourth to show a new screen from the downloaded xap.&amp;nbsp; After each yield statement, the compiler will &amp;ldquo;pause&amp;rdquo; the execution of this method until that particular task completes. The first, third and fourth tasks are synchronous, while the second is asynchronous.&amp;nbsp; But the yield syntax allows you to write all the code in a sequential fashion, preserving the original workflow as a much more readable and declarative structure. To understand a bit more how this works, have a look at the IResult interface:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;public interface IResult
{
    void Execute(ActionExecutionContext context);
    event EventHandler&amp;lt;ResultCompletionEventArgs&amp;gt; Completed;
}&lt;/pre&gt;
&lt;p&gt;It&amp;rsquo;s a fairly simple interface to implement. Simply write your code in the &amp;ldquo;Execute&amp;rdquo; method and be sure to raise the &amp;ldquo;Completed&amp;rdquo; event when you are done, whether it be a synchronous or an asynchronous task. Because coroutines occur inside of an Action, we provide you with an ActionExecutionContext useful in building UI-related IResult implementations. This allows the ViewModel a way to declaratively state it intentions in controlling the view without having any reference to a View or the need for interaction-based unit testing. Here&amp;rsquo;s what the ActionResultContext looks like:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;public class ActionExecutionContext
{
    public ActionMessage Message;
    public FrameworkElement Source;
    public object EventArgs;
    public object Target;
    public DependencyObject View;
    public MethodInfo Method;
    public Func&amp;lt;bool&amp;gt; CanExecute;
    public object this[string key];
}&lt;/pre&gt;
&lt;p&gt;And here&amp;rsquo;s an explanation of what all these properties mean:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Message &amp;ndash; The original ActionMessage that caused the invocation of this IResult.&lt;/li&gt;
&lt;li&gt;Source &amp;ndash; The FrameworkElement that triggered the execution of the Action.&lt;/li&gt;
&lt;li&gt;EventArgs &amp;ndash; Any event arguments associated with the trigger of the Action.&lt;/li&gt;
&lt;li&gt;Target &amp;ndash; The class instance on which the actual Action method exists.&lt;/li&gt;
&lt;li&gt;View &amp;ndash; The view associated with the Target.&lt;/li&gt;
&lt;li&gt;Method &amp;ndash; The MethodInfo specifying which method to invoke on the Target instance.&lt;/li&gt;
&lt;li&gt;CanExecute &amp;ndash; A function that returns true if the Action can be invoked, false otherwise.&lt;/li&gt;
&lt;li&gt;Key Index: A place to store/retrieve any additional metadata which may be used by extensions to the framework.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bearing that in mind, I wrote a naive Loader IResult that searches the VisualTree looking for the first instance of a BusyIndicator to use to display a loading message. Here&amp;rsquo;s the implementation:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System;
using System.Windows;
using System.Windows.Controls;

public class Loader : IResult
{
    readonly string message;
    readonly bool hide;

    public Loader(string message)
    {
        this.message = message;
    }

    public Loader(bool hide)
    {
        this.hide = hide;
    }

    public void Execute(ActionExecutionContext context)
    {
        var view = context.View as FrameworkElement;
        while(view != null)
        {
            var busyIndicator = view as BusyIndicator;
            if(busyIndicator != null)
            {
                if(!string.IsNullOrEmpty(message))
                    busyIndicator.BusyContent = message;
                busyIndicator.IsBusy = !hide;
                break;
            }

            view = view.Parent as FrameworkElement;
        }

        Completed(this, new ResultCompletionEventArgs());
    }

    public event EventHandler&amp;lt;ResultCompletionEventArgs&amp;gt; Completed = delegate { };

    public static IResult Show(string message = null)
    {
        return new Loader(message);
    }

    public static IResult Hide()
    {
        return new Loader(true);
    }
}&lt;/pre&gt;
&lt;p&gt;See how I took advantage of context.View? This opens up a lot of possibilities while maintaining separation between the view and the view model. Just to list a few interesting things you could do with IResult implementations: show a message box, show a VM-based modal dialog, show a VM-based Popup at the user&amp;rsquo;s mouse position, play an animation, show File Save/Load dialogs, place focus on a particular UI element based on VM properties rather than controls, etc. Of coarse, one of the biggest opportunities is calling web services. Let&amp;rsquo;s look at how you might do that, but by using a slightly different scenario, dynamically downloading a xap:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.ReflectionModel;
using System.Linq;

public class LoadCatalog : IResult
{
    static readonly Dictionary&amp;lt;string, DeploymentCatalog&amp;gt; Catalogs = new Dictionary&amp;lt;string, DeploymentCatalog&amp;gt;();
    readonly string uri;

    [Import]
    public AggregateCatalog Catalog { get; set; }

    public LoadCatalog(string relativeUri)
    {
        uri = relativeUri;
    }

    public void Execute(ActionExecutionContext context)
    {
        DeploymentCatalog catalog;

        if(Catalogs.TryGetValue(uri, out catalog))
            Completed(this, new ResultCompletionEventArgs());
        else
        {
            catalog = new DeploymentCatalog(uri);
            catalog.DownloadCompleted += (s, e) =&amp;gt;{
                if(e.Error == null)
                {
                    Catalogs[uri] = catalog;
                    Catalog.Catalogs.Add(catalog);
                    catalog.Parts
                        .Select(part =&amp;gt; ReflectionModelServices.GetPartType(part).Value.Assembly)
                        .Where(assembly =&amp;gt; !AssemblySource.Instance.Contains(assembly))
                        .Apply(x =&amp;gt; AssemblySource.Instance.Add(x));
                }
                else Loader.Hide().Execute(context);

                Completed(this, new ResultCompletionEventArgs {
                    Error = e.Error,
                    WasCancelled = false
                });
            };

            catalog.DownloadAsync();
        }
    }

    public event EventHandler&amp;lt;ResultCompletionEventArgs&amp;gt; Completed = delegate { };
}&lt;/pre&gt;
&lt;p&gt;In case it wasn&amp;rsquo;t clear, this sample is using MEF. Furthermore, we are taking advantage of the DeploymentCatalog created for Silverlight 4.&amp;nbsp; You don&amp;rsquo;t really need to know a lot about MEF or DeploymentCatalog to get the takeaway. Just take note of the fact that we wire for the DownloadCompleted event and make sure to fire the IResult.Completed event in its handler. This is what enables the async pattern to work. We also make sure to check the error and pass that along in the ResultCompletionEventArgs. Speaking of that, here&amp;rsquo;s what that class looks like:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;public class ResultCompletionEventArgs : EventArgs
{
    public Exception Error;
    public bool WasCancelled;
}&lt;/pre&gt;
&lt;p&gt;Caliburn.Micro&amp;rsquo;s enumerator checks these properties after it get&amp;rsquo;s called back from each IResult. If there is either an error or WasCancelled is set to true, we stop execution. You can use this to your advantage. Let&amp;rsquo;s say you create an IResult for the OpenFileDialog. You could check the result of that dialog, and if the user canceled it, set WasCancelled on the event args. By doing this, you can write an action that assumes that if the code following the Dialog.Show executes, the user must have selected a file. This sort of technique can simplify the logic in such situations. Obviously, you could use the same technique for the SaveFileDialog or any confirmation style message box if you so desired. My favorite part of the LoadCatalog implementation shown above, is that the original implementation was written by a CM user! Thanks janoveh for this awesome submission! As a side note, one of the things we added to the CM project site is &lt;a target="_blank" href="http://caliburnmicro.codeplex.com/documentation"&gt;a &amp;ldquo;Recipes&amp;rdquo; section&lt;/a&gt;. We are going to be adding more common solutions such as this to that area in the coming months. So, it will be a great place to check for cool plugins and customizations to the framework.***&lt;/p&gt;
&lt;p&gt;Another thing you can do is create a series of IResult implementations built around your application&amp;rsquo;s shell. That is what the ShowScreen result used above does. Here is its implementation:&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System;
using System.ComponentModel.Composition;

public class ShowScreen : IResult
{
    readonly Type screenType;
    readonly string name;

    [Import]
    public IShell Shell { get; set; }

    public ShowScreen(string name)
    {
        this.name = name;
    }

    public ShowScreen(Type screenType)
    {
        this.screenType = screenType;
    }

    public void Execute(ActionExecutionContext context)
    {
        var screen = !string.IsNullOrEmpty(name)
            ? IoC.Get&amp;lt;object&amp;gt;(name)
            : IoC.GetInstance(screenType, null);

        Shell.ActivateItem(screen);
        Completed(this, new ResultCompletionEventArgs());
    }

    public event EventHandler&amp;lt;ResultCompletionEventArgs&amp;gt; Completed = delegate { };

    public static ShowScreen Of&amp;lt;T&amp;gt;()
    {
        return new ShowScreen(typeof(T));
    }
}&lt;/pre&gt;
&lt;p&gt;This bring up another important feature of IResult. Before CM executes a result, it passes it through the IoC.BuildUp method allowing your container the opportunity to push dependencies in through the properties. This allows you to create them normally within your view models, while still allowing them to take dependencies on application services. In this case, we depend on IShell. You could also have your container injected, but in this case I chose to use the IoC static class internally. As a general rule, you should avoid pulling things from the container directly. However, I think it is acceptable when done inside of infrastructure code such as a ShowScreen IResult.&lt;/p&gt;
&lt;p&gt;I hope this gives some explanation and creative ideas for what can be accomplished with IResult. Be sure to check out the sample application attached. There&amp;rsquo;s a few other interesting things in there as well.&lt;/p&gt;
&lt;p&gt;* When I went to look up the &amp;ldquo;official&amp;rdquo; definition on wikipedia I was interested to see what it had to say about implementations in various languages. Scrolling down to the section on C#&amp;hellip;Caliburn was listed! Fun stuff. &lt;/p&gt;
&lt;p&gt;** You can also return a single instance of IResult without using IEnuermable&amp;lt;IResult&amp;gt; if you just want a simple way to execute a single task.&lt;/p&gt;
&lt;p&gt;*** If you want a sample of a truly awesome plugin we will be adding to the recipes section soon, &lt;a target="_blank" href="http://marcoamendola.wordpress.com/2010/08/10/a-caliburn-micro-recipe-filters/"&gt;check this out!&lt;/a&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=61612" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.06.16.12/Caliburn.Micro.Coroutines.zip" length="26128" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF_2F00_e/default.aspx">WPF/e</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/DSL/default.aspx">DSL</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/RIA/default.aspx">RIA</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Tutorial/default.aspx">Tutorial</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/UI+Architecture/default.aspx">UI Architecture</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn+Micro/default.aspx">Caliburn Micro</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WP7/default.aspx">WP7</category></item><item><title>Caliburn.Micro Soup to Nuts Pt. 3 – All About Actions</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/17/caliburn-micro-soup-to-nuts-pt-3-all-about-actions.aspx</link><pubDate>Sat, 17 Jul 2010 16:04:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:61112</guid><dc:creator>Rob Eisenberg</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/rob_eisenberg/rsscomments.aspx?PostID=61112</wfw:commentRss><comments>http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/17/caliburn-micro-soup-to-nuts-pt-3-all-about-actions.aspx#comments</comments><description>&lt;p&gt;We briefly introduced actions in &lt;a target="_blank" href="http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/06/caliburn-micro-soup-to-nuts-pt-1-configuration-actions-and-conventions.aspx"&gt;Pt. 1&lt;/a&gt;, but there is so much more to know. To begin our investigation, we&amp;rsquo;ll take our simple &amp;ldquo;Hello&amp;rdquo; example and see what it looks like when we explicitly create the actions rather than use conventions. Here&amp;rsquo;s the Xaml:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;UserControl x:Class=&amp;quot;Caliburn.Micro.Hello.ShellView&amp;quot;
             xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
             xmlns:i=&amp;quot;clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity&amp;quot;
             xmlns:cal=&amp;quot;http://www.caliburnproject.org&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBox x:Name=&amp;quot;Name&amp;quot; /&amp;gt;
        &amp;lt;Button Content=&amp;quot;Click Me&amp;quot;&amp;gt;
            &amp;lt;i:Interaction.Triggers&amp;gt;
                &amp;lt;i:EventTrigger EventName=&amp;quot;Click&amp;quot;&amp;gt;
                    &amp;lt;cal:ActionMessage MethodName=&amp;quot;SayHello&amp;quot; /&amp;gt;
                &amp;lt;/i:EventTrigger&amp;gt;
            &amp;lt;/i:Interaction.Triggers&amp;gt;
        &amp;lt;/Button&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;As you can see, the Actions feature leverages System.Windows.Interactivity for it&amp;rsquo;s trigger mechanism. This means that you can use anything that inherits from System.Windows.Interactivity.TriggerBase to trigger the sending of an ActionMessage.*&amp;nbsp; Perhaps the most common trigger is an EventTrigger, but you can create almost any kind of trigger imaginable or leverage some common triggers already created by the community.&amp;nbsp; ActionMessage is, of coarse, the Caliburn.Micro-specific part of this markup. It indicates that when the trigger occurs, we should send a message of &amp;ldquo;SayHello.&amp;rdquo;&amp;nbsp; So, why do I use the language &amp;ldquo;send a message&amp;rdquo; instead of &amp;ldquo;execute a method&amp;rdquo; when describing this functionality? That&amp;rsquo;s the interesting and powerful part.&amp;nbsp; ActionMessage bubbles through the Visual Tree searching for a target instance that can handle it. If a target is found, but does not have a &amp;ldquo;SayHello&amp;rdquo; method, the framework will continue to bubble until it finds one, throwing an exception if no &amp;ldquo;handler&amp;rdquo; is found.** This bubbling nature of ActionMessage comes in handy in a number of interesting scenarios, Master/Details being a key use case. Another important feature to note is Action guards. When a handler is found for the &amp;ldquo;SayHello&amp;rdquo; message, it will check to see if that class also has either a property or a method named &amp;ldquo;CanSayHello.&amp;rdquo; If you have a guard property and your class implements INotifyPropertyChanged, then the framework will observe changes in that property and re-evaluate the guard accordingly. We&amp;rsquo;ll discuss method guards in further detail below.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;re probably wondering how to specify the target of an ActionMessage. Looking at the markup above, there&amp;rsquo;s no visible indication of what that target will be. So, where does that come from? Since we used a Model-First approach, when Caliburn.Micro (hereafter CM) created the view and bound it to the ViewModel using the ViewModelBinder, it set this up for us. Anything that goes through the ViewModelBinder will have its action target set automatically. But, you can set it yourself as well, using the attached property Action.Target. Setting this property positions an ActionMessage &amp;ldquo;handler&amp;rdquo; in the Visual Tree attached to the node on with you declare the property. It also sets the DataContext to the same value, since you often want these two things to be the same. However, you can vary the Action.Target from the DataContext if you like. Simply use the Action.TargetWithoutContext attached property instead. One nice thing about Action.Target is that you can set it to a System.String and CM will use that string to resolve an instance from the IoC container using the provided value as its key. This gives you a nice way of doing View-First MVVM if you so desire. If you want Action.Target set and you want Action/Binding Conventions applied as well, you can use the Bind.Model attached property in the same way.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how we would apply this to achieve MVVM using a View-First technique (gasp!) Here&amp;rsquo;s how we would change our bootstrapper:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;public class MefBootstrapper : Bootstrapper
{
    //same as before

    protected override void DisplayRootView()
    {
        Application.Current.RootVisual = new ShellView();
    }

    //same as before
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Because we are using View-First, we&amp;rsquo;ve inherited from the non-generic Bootstrapper. The MEF configuration is the same as seen previously, so I have left that out for brevity&amp;rsquo;s sake. The only other thing that is changed is how the view gets created. In this scenario, we simply override DisplayRootView, instantiate the view ourselves and set it as the RootVisual (or call Show in the case of WPF). Next, we&amp;rsquo;ll slightly alter how we are exporting our ShellViewModel, by adding an explicitly named contract:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;[Export(&amp;quot;Shell&amp;quot;, typeof(IShell))]
public class ShellViewModel : PropertyChangedBase, IShell
{
    //same as before
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Finally, we will alter our view to pull in the VM and perform all bindings:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;UserControl x:Class=&amp;quot;Caliburn.Micro.ViewFirst.ShellView&amp;quot;
             xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
             xmlns:cal=&amp;quot;http://www.caliburnproject.org&amp;quot;
             cal:Bind.Model=&amp;quot;Shell&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBox x:Name=&amp;quot;Name&amp;quot; /&amp;gt;
        &amp;lt;Button x:Name=&amp;quot;SayHello&amp;quot;
                Content=&amp;quot;Click Me&amp;quot; /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Notice the use of the Bind.Model attached property. This resolves our VM by key from the IoC container, sets the Action.Target and DataContext and applies all conventions. I thought it would be nice to show how View-First development is fully supported with CM, but mainly I want to make clear the various ways that you can set targets for actions and the implications of using each technique. Here&amp;rsquo;s a summary of the available attached properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Action.Target &amp;ndash; Sets both the Action.Target property and the DataContext property to the specified instance. String values are used to resolve an instance from the IoC container. &lt;/li&gt;
&lt;li&gt;Action.TargetWithoutContext &amp;ndash; Sets only the Action.Target property to the specified instance. String values are used to resolve an instance from the IoC container. &lt;/li&gt;
&lt;li&gt;Bind.Model &amp;ndash; View-First - Set&amp;rsquo;s the Action.Target and DataContext properties to the specified instance. Applies conventions to the view. String values are used to resolve an instance from the IoC container. &lt;/li&gt;
&lt;li&gt;View.Model &amp;ndash; ViewModel-First &amp;ndash; Locates the view for the specified VM instance and injects it at the content site. Sets the VM to the Action.Target and the DataContext. Applies conventions to the view. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s take a look at another interesting aspect of ActionMessage: Parameters. To see this in action, let&amp;rsquo;s switch back to our original ViewModel-First bootstrapper, etc. and begin by changing our ShellViewModel to look like this: &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System.ComponentModel.Composition;
using System.Windows;

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    public bool CanSayHello(string name)
    {
        return !string.IsNullOrWhiteSpace(name);
    }

    public void SayHello(string name)
    {
        MessageBox.Show(string.Format(&amp;quot;Hello {0}!&amp;quot;, name));
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are a few things to note here. First, we are now working with a completely POCO class; no INPC goop here. Second, we have added an input parameter to our SayHello method. Finally, we changed our CanSayHello property into a method with the same inputs as the action, but with a bool return type. Now, let&amp;rsquo;s have a look at the Xaml:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;UserControl x:Class=&amp;quot;Caliburn.Micro.HelloParameters.ShellView&amp;quot;
             xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
             xmlns:i=&amp;quot;clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity&amp;quot;
             xmlns:cal=&amp;quot;http://www.caliburnproject.org&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBox x:Name=&amp;quot;Name&amp;quot; /&amp;gt;
        &amp;lt;Button Content=&amp;quot;Click Me&amp;quot;&amp;gt;
            &amp;lt;i:Interaction.Triggers&amp;gt;
                &amp;lt;i:EventTrigger EventName=&amp;quot;Click&amp;quot;&amp;gt;
                    &amp;lt;cal:ActionMessage MethodName=&amp;quot;SayHello&amp;quot;&amp;gt;
                        &amp;lt;cal:Parameter Value=&amp;quot;{Binding ElementName=Name, Path=Text}&amp;quot; /&amp;gt;
                    &amp;lt;/cal:ActionMessage&amp;gt;
                &amp;lt;/i:EventTrigger&amp;gt;
            &amp;lt;/i:Interaction.Triggers&amp;gt;
        &amp;lt;/Button&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Our markup now has one modification: We declared the parameter as part of the ActionMessage using an ElementName Binding. You can have any number of parameters you desire. Value is a DependencyProperty, so all the standard binding capabilities apply to parameters. Did I mention you can do all this in Blend?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/ActionsInBlend_5F00_363545A1.jpg"&gt;&lt;img height="161" width="244" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/rob_5F00_eisenberg/ActionsInBlend_5F00_thumb_5F00_0CC10461.jpg" alt="ActionsInBlend" border="0" title="ActionsInBlend" style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;One thing that is nice about this is that every time the value of a parameter changes, we&amp;rsquo;ll call the guard method associated with the action(CanSayHello in this case) and use its result to update the UI that the ActionMessage is attached to. Go ahead and run the application. You&amp;rsquo;ll see that it behaves the same as in previous examples.&lt;/p&gt;
&lt;p&gt;In addition to literal values and Binding Expressions, there are a number of helpful &amp;ldquo;special&amp;rdquo; values that you can use with parameters. These allow you a convenient way to access common contextual information:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$eventArgs &amp;ndash; Passes the Trigger&amp;rsquo;s EventArgs or input parameter to your Action. Note: This will be null for guard methods since the trigger hasn&amp;rsquo;t actually occurred. &lt;/li&gt;
&lt;li&gt;$dataContext &amp;ndash; Passes the DataContext of the element that the ActionMessage is attached to. This is very useful in Master/Detail scenarios where the ActionMessage may bubble to a parent VM but needs to carry with it the child instance to be acted upon. &lt;/li&gt;
&lt;li&gt;$source &amp;ndash; The actual FrameworkElement that triggered the ActionMessage to be sent. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You must start the variable with a &amp;ldquo;$&amp;rdquo; but the name is treated in a case-insensitive way by CM.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Word to the Wise&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Parameters are a convenience feature. They are very powerful and can help you out of some tricky spots, but they can be easily abused. Personally, I only use parameters in the simplest scenarios. One place where they have worked nicely for me is in login forms. Another scenario, as mentioned previously is Master/Detail operations.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, do you want to see something truly wicked? Change your Xaml back to this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;UserControl x:Class=&amp;quot;Caliburn.Micro.HelloParameters.ShellView&amp;quot;
             xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;TextBox x:Name=&amp;quot;Name&amp;quot; /&amp;gt;
        &amp;lt;Button x:Name=&amp;quot;SayHello&amp;quot; 
                Content=&amp;quot;Click Me&amp;quot; /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Running the application will confirm for you that CM&amp;rsquo;s conventions even understand ActionMessage parameters. We&amp;rsquo;ll discuss conventions a lot more in the future, but you should be happy to know that these conventions are case-insensitive and can even detect the before-mentioned &amp;ldquo;special&amp;rdquo; values.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, lets look at a simple Master/Detail scenario that demonstrates ActionMessage bubbling, but let&amp;rsquo;s do it with a shorthand syntax that is designed to be more developer friendly. We&amp;rsquo;ll start by adding a simple new class named Model:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System;

public class Model
{
    public Guid Id { get; set; }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;And then we&amp;rsquo;ll change our ShellViewModel to this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="c#:nogutter:nocontrols"&gt;using System;
using System.ComponentModel.Composition;

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    public BindableCollection&amp;lt;Model&amp;gt; Items { get; private set; }

    public ShellViewModel()
    {
        Items = new BindableCollection&amp;lt;Model&amp;gt;{
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() },
            new Model { Id = Guid.NewGuid() }
        };
    }

    public void Add()
    {
        Items.Add(new Model { Id = Guid.NewGuid() });
    }

    public void Remove(Model child)
    {
        Items.Remove(child);
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now our shell has a collection of Model instances along with the ability to add or remove from the collection. Notice that the Remove method takes a single parameter of type Model. Now, let&amp;rsquo;s update the ShellView:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;UserControl x:Class=&amp;quot;Caliburn.Micro.BubblingAction.ShellView&amp;quot;
             xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
             xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
             xmlns:cal=&amp;quot;http://www.caliburnproject.org&amp;quot;&amp;gt;
    &amp;lt;StackPanel&amp;gt;
        &amp;lt;ItemsControl x:Name=&amp;quot;Items&amp;quot;&amp;gt;
            &amp;lt;ItemsControl.ItemTemplate&amp;gt;
                &amp;lt;DataTemplate&amp;gt;
                    &amp;lt;StackPanel Orientation=&amp;quot;Horizontal&amp;quot;&amp;gt;
                        &amp;lt;Button Content=&amp;quot;Remove&amp;quot;
                                cal:Message.Attach=&amp;quot;Remove($dataContext)&amp;quot; /&amp;gt;
                        &amp;lt;TextBlock Text=&amp;quot;{Binding Id}&amp;quot; /&amp;gt;
                    &amp;lt;/StackPanel&amp;gt;
                &amp;lt;/DataTemplate&amp;gt;
            &amp;lt;/ItemsControl.ItemTemplate&amp;gt;
        &amp;lt;/ItemsControl&amp;gt;
        &amp;lt;Button Content=&amp;quot;Add&amp;quot;
                cal:Message.Attach=&amp;quot;Add&amp;quot; /&amp;gt;
    &amp;lt;/StackPanel&amp;gt;
&amp;lt;/UserControl&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The first thing to notice is that we are using a more Xaml-developer-friendly mechanism for declaring our ActionMessages. The Message.Attach property is backed by a simple parser which takes its textual input and transforms it into the full Interaction.Trigger/ActionMessage that you&amp;rsquo;ve seen previously. If you work primarily in the Xaml editor and not in the designer, you&amp;rsquo;re going to like Message.Attach. Notice that neither Message.Attach declarations specify which event should send the message. If you leave off the event, the parser will use the ConventionManager to determine the default event to use for the trigger. In the case of Button, it&amp;rsquo;s Click. You can always be explicit of coarse. Here&amp;rsquo;s what the full syntax for our Remove message would look like if we were declaring everything:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;Button Content=&amp;quot;Remove&amp;quot;
        cal:Message.Attach=&amp;quot;[Event Click] = [Action Remove($dataContext)]&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Suppose we were to re-write our parameterized SayHello action with the Message.Attach syntax. It would look like this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;Button Content=&amp;quot;Click Me&amp;quot;
        cal:Message.Attach=&amp;quot;[Event Click] = [Action SayHello(Name.Text)]&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;But we could also leverage some smart defaults of the parser and do it like this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;Button Content=&amp;quot;Click Me&amp;quot;
        cal:Message.Attach=&amp;quot;SayHello(Name)&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You can specify literals as parameters as well and even declare multiple actions by separating them with a semicolon:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre name="code" class="xml:nogutter:nocontrols"&gt;&amp;lt;Button Content=&amp;quot;Let&amp;#39;s Talk&amp;quot;
        cal:Message.Attach=&amp;quot;[Event MouseEnter] = [Action Talk(&amp;#39;Hello&amp;#39;, Name.Text)];
                            [Event MouseLeave] = [Action Talk(&amp;#39;Goodbye&amp;#39;, Name.Text)]&amp;quot; /&amp;gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;WARNING: Those developers who ask me to expand this functionality into a full-blown expression parser will be taken out back and&amp;hellip;dealt with. Message.Attach is not about cramming code into Xaml. It&amp;rsquo;s purpose is to provide a streamlined syntax for declaring when/what messages to send to the ViewModel. Please don&amp;rsquo;t abuse this.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you haven&amp;rsquo;t already, run the application. Any doubts you had will hopefully be put to rest when you see that the message bubbling works as advertised :) Something else I would like to point out is that CM automatically performs type-conversion on parameters. So, for example, you can pump TextBox.Text into a System.Double parameter without any fear of a casting issue.&lt;/p&gt;
&lt;p&gt;So, we&amp;rsquo;ve discussed using Interaction.Triggers with ActionMessage, including the use of Parameters with literals, element bindings*** and special values. We&amp;rsquo;ve discussed the various ways to set the action target depending on your needs/architectural style: Action.Target, Action.TargetWithoutContext, Bind.Model or View.Model. We also saw an example of the bubbling nature of ActionMessage and demoed it using the streamlined Message.Attach syntax. All along the way we&amp;rsquo;ve looked at various examples of conventions in action too. Now, there&amp;rsquo;s one final killer feature of ActionMessage we haven&amp;rsquo;t discussed yet&amp;hellip;Coroutines. But, that will have to wait until next time.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;*Currently, the full version of Caliburn is not based on System.Windows.Interactivity. Caliburn&amp;rsquo;s trigger mechanism was around long before Blend&amp;rsquo;s.&amp;nbsp; You may notice a shocking similarity in the markup. That said, Caliburn v2.0 will be migrated to use the Blend model in the near future.&lt;/p&gt;
&lt;p&gt;**Actually, if no handler is found, before an exception is thrown, the framework will check the current DataContext to see if it has the requested method. This seamed like a reasonable fallback behavior.&lt;/p&gt;
&lt;p&gt;***One important detail about ElementName Bindings that I didn&amp;rsquo;t mention&amp;hellip;It doesn&amp;rsquo;t work with WP7 currently. Due to the fact that WP7 is based on a version of Silverlight 3 which had an incomplete implementation of DependencyObject/DependencyProperty, the infrastructure is not present to make this work in any sort of sane way. However, parameter literals and special values still work as described along with all the rest of the ActionMessage features.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=61112" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.06.11.12/Samples.zip" length="30486" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Xaml/default.aspx">Xaml</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/databinding/default.aspx">databinding</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF_2F00_e/default.aspx">WPF/e</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/RIA/default.aspx">RIA</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Tutorial/default.aspx">Tutorial</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/UI+Architecture/default.aspx">UI Architecture</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn+Micro/default.aspx">Caliburn Micro</category></item><item><title>Caliburn.Micro Soup to Nuts Pt. 2 – Customizing The Bootstrapper</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/caliburn-micro-soup-to-nuts-pt-2-customizing-the-bootstrapper.aspx</link><pubDate>Fri, 09 Jul 2010 00:28:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:61031</guid><dc:creator>Rob Eisenberg</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/rob_eisenberg/rsscomments.aspx?PostID=61031</wfw:commentRss><comments>http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/08/caliburn-micro-soup-to-nuts-pt-2-customizing-the-bootstrapper.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://devlicio.us/blogs/rob_eisenberg/archive/2010/07/06/caliburn-micro-soup-to-nuts-pt-1-configuration-actions-and-conventions.aspx" target="_blank"&gt;In the last part&lt;/a&gt; we discussed the most basic configuration for &lt;a href="http://caliburnmicro.codeplex.com/" target="_blank"&gt;Caliburn.Micro&lt;/a&gt; and demonstrated a couple of simple features related to Actions and Conventions. In this part, I would like to explore the Bootstrapper class a little more. Let&amp;rsquo;s begin by configuring our application to use an IoC container. We&amp;rsquo;ll use MEF for this example, but Caliburn.Micro will work well with any container. First, go ahead and &lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.06.09.93/Caliburn.Micro.Hello.zip" target="_blank"&gt;grab the code from Part 1&lt;/a&gt;. We are going to use that as our starting point. Add two additional references: System.ComponentModel.Composition and System.ComponentModel.Composition.Initialization. Those are the assemblies that contain MEF&amp;rsquo;s functionality.* Now, let&amp;rsquo;s create a new Bootstrapper called MefBootstrapper. Use the following code:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Primitives;
using System.Linq;

public class MefBootstrapper : Bootstrapper&amp;lt;IShell&amp;gt;
{
    private CompositionContainer container;

    protected override void Configure()
    {
        container = CompositionHost.Initialize(
            new AggregateCatalog(
                AssemblySource.Instance.Select(x =&amp;gt; new AssemblyCatalog(x)).OfType&amp;lt;ComposablePartCatalog&amp;gt;()
                )
            );

        var batch = new CompositionBatch();

        batch.AddExportedValue&amp;lt;IWindowManager&amp;gt;(new WindowManager());
        batch.AddExportedValue&amp;lt;IEventAggregator&amp;gt;(new EventAggregator());
        batch.AddExportedValue(container);

        container.Compose(batch);
    }

    protected override object GetInstance(Type serviceType, string key)
    {
        string contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
        var exports = container.GetExportedValues&amp;lt;object&amp;gt;(contract);

        if (exports.Count() &amp;gt; 0)
            return exports.First();

        throw new Exception(string.Format(&amp;quot;Could not locate any instances of contract {0}.&amp;quot;, contract));
    }

    protected override IEnumerable&amp;lt;object&amp;gt; GetAllInstances(Type serviceType)
    {
        return container.GetExportedValues&amp;lt;object&amp;gt;(AttributedModelServices.GetContractName(serviceType));
    }

    protected override void BuildUp(object instance)
    {
        container.SatisfyImportsOnce(instance);
    }
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all the code to integrate MEF.&amp;nbsp; First, we override the Configure method of the Bootstrapper class. This gives us an opportunity to set up our IoC container as well as perform any other framework configuration we may want to do, such as customizing conventions. In this case, I&amp;rsquo;m taking advantage of Silverlight&amp;rsquo;s CompositionHost to setup the CompositionContainer. You can just instantiate the container directly if you are working with .NET. Then, I&amp;rsquo;m creating an AggregateCatalog and populating it with AssemblyCatalogs; one for each Assembly in AssemblySource.Instance. So, what is AssemblySoure.Instance? This is the place that Caliburn.Micro looks for Views. You can add assemblies to this at any time during your application to make them available to the framework, but there is also a special place to do it in the Bootstrapper. Simply override SelectAssemblies like this:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;protected override IEnumerable&amp;lt;Assembly&amp;gt; SelectAssemblies()
{
    return new[] {
        Assembly.GetExecutingAssembly()
    };
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;All you have to do is return a list of searchable assemblies. By default, the base class returns the assembly that your Application exists in. So, if all your views are in the same assembly as your application, you don&amp;rsquo;t even need to worry about this. If you have multiple referenced assemblies that contain views, this is an extension point you need to remember. Also, if you are dynamically loading modules, you&amp;rsquo;ll need to make sure they get registered with your IoC container and the AssemblySoure.Instance when they are loaded. &lt;/p&gt;
&lt;p&gt;After creating the container and providing it with the catalogs, I make sure to add a few Caliburn.Micro-specific services. The framework provides default implementations of both IWindowManager and IEventAggregator. Those are pieces that I&amp;rsquo;m likely to take dependencies on elsewhere, so I want them to be available for injection. I also register the container with itself (just a personal preference).&lt;/p&gt;
&lt;p&gt;After we configure the container, we need to tell Caliburn.Micro how to use it.&amp;nbsp; That is the purpose of the three overrides that follow. &amp;ldquo;GetInstance&amp;rdquo; and &amp;ldquo;GetAllInstances&amp;rdquo; are required by the framework. &amp;ldquo;BuildUp&amp;rdquo; is optionally used to supply property dependencies to instances of IResult that are executed by the framework. &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Word to the Wise&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;While Caliburn.Micro does provide ServiceLocator functionality through the Bootstrapper&amp;rsquo;s overrides and the IoC class, you should avoid using this directly in your application code. ServiceLocator is considered by many to be an anti-pattern. Pulling from a container tends to obscure the intent of the dependent code and can make testing more complicated. In future articles I will demonstrate at least one scenario where you may be tempted to access the ServiceLocator from a ViewModel. I&amp;rsquo;ll also demonstrate some solutions.**&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Besides what is shown above, there are some other notable methods on the Bootstrapper. You can override OnStartup and OnExit to execute code when the application starts or shuts down respectively and OnUnhandledException to cleanup after any exception that wasn&amp;rsquo;t specifically handled by your application code.&amp;nbsp; The last override, DisplayRootView, is unique. Let&amp;rsquo;s look at how it is implemented in Bootstrapper&amp;lt;TRootModel&amp;gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;protected override void DisplayRootView() 
{
    var viewModel = IoC.Get&amp;lt;TRootModel&amp;gt;();
#if SILVERLIGHT
    var view = ViewLocator.LocateForModel(viewModel, null, null);
    ViewModelBinder.Bind(viewModel, view, null);

    var activator = viewModel as IActivate;
    if (activator != null)
        activator.Activate();

    Application.Current.RootVisual = view;
#else
    new WindowManager().Show(viewModel);
#endif
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The Silverlight version of this method resolves your root VM from the container, locates the view for it and binds the two together. It then makes sure to &amp;ldquo;activate&amp;rdquo; the VM if it implements the appropriate interface. The WPF version does the same thing by using the WindowManager class, more or less. DisplayRootView is basically a convenience implementation for model-first development. If you don&amp;rsquo;t like it, perhaps because you prefer view-first MVVM, then this is the method you want to override to change that behavior.&lt;/p&gt;
&lt;p&gt;Now that you understand all about the Bootstrapper, let&amp;rsquo;s get our sample working. We need to add the IShell interface. In our case, it&amp;rsquo;s just a marker interface. But, in a real application, you would&amp;nbsp; have some significant shell-related functionality baked into this contract. Here&amp;rsquo;s the code:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;public interface IShell
{
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Now, we need to implement the interface and decorate our ShellViewModel with the appropriate MEF attributes:&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class="c#:nogutter:nocontrols" name="code"&gt;[Export(typeof(IShell))]
public class ShellViewModel : PropertyChangedBase, IShell
{
   ...implementation is same as before...
}&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s it! Your up and running with your bootstrapper configured for MEF.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;*If you are using .NET, you will only need to reference System.ComponentModel.Composition.&lt;/p&gt;
&lt;p&gt;**I&amp;rsquo;m quite guilty of this myself, but I&amp;rsquo;m trying to be more conscious of it.&amp;nbsp; I&amp;rsquo;m also excited to see that modern IoC containers as well as Caliburn.Micro provide some very nice ways to avoid this situation.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=61031" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.06.10.31/Caliburn.Micro.HelloMef.zip" length="7463" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Xaml/default.aspx">Xaml</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/databinding/default.aspx">databinding</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF_2F00_e/default.aspx">WPF/e</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/RIA/default.aspx">RIA</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Tutorial/default.aspx">Tutorial</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/UI+Architecture/default.aspx">UI Architecture</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn+Micro/default.aspx">Caliburn Micro</category></item><item><title>“Build Your Own MVVM Framework” is Online</title><link>http://devlicio.us/blogs/rob_eisenberg/archive/2010/03/16/build-your-own-mvvm-framework-is-online.aspx</link><pubDate>Tue, 16 Mar 2010 22:37:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:56116</guid><dc:creator>Rob Eisenberg</dc:creator><slash:comments>42</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/rob_eisenberg/rsscomments.aspx?PostID=56116</wfw:commentRss><comments>http://devlicio.us/blogs/rob_eisenberg/archive/2010/03/16/build-your-own-mvvm-framework-is-online.aspx#comments</comments><description>&lt;p&gt;Yesterday I delivered my talk, &lt;a href="http://live.visitmix.com/MIX10/Sessions/EX15"&gt;&amp;ldquo;Build Your Own MVVM Framework,&amp;rdquo;&lt;/a&gt; at Mix.&amp;nbsp; Thanks to all who came out to listen and allow me a short time to share some of my ideas.&amp;nbsp; I&amp;rsquo;m very grateful to have had this opportunity.&amp;nbsp; Thanks also to all who voted for the talk.&amp;nbsp; If you were not able to make it in person, Microsoft has made the video of the session available online along with the slides.&amp;nbsp; You can now watch it at &lt;a href="http://live.visitmix.com/MIX10/Sessions/EX15"&gt;http://live.visitmix.com/MIX10/Sessions/EX15&lt;/a&gt;. I&amp;rsquo;m also providing the full source code for the sample application as an attachment to this blog post.&amp;nbsp; If you look at the source code, there are a few things to keep in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The backend is fake.&lt;/li&gt;
&lt;li&gt;The framework is not intended to be used &amp;ldquo;as is.&amp;rdquo; It was built for this &lt;em&gt;specific &lt;/em&gt;application. You should adapt it to your application, or use &lt;a href="http://caliburnproject.org/"&gt;Caliburn&lt;/a&gt;, which &lt;em&gt;was&lt;/em&gt; designed for general use.&lt;/li&gt;
&lt;li&gt;There are a number of other interesting things in the sample, which I did not discuss in the talk. It&amp;rsquo;s worth poking around a little bit&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I hope this talk and sample give you some ideas. I would love to hear your feedback.&amp;nbsp; Enjoy!&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=56116" width="1" height="1"&gt;</description><enclosure url="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Components.PostAttachments/00.00.05.61.16/Build-Your-Own-MVVM-Framework.zip" length="149731" type="application/x-zip-compressed" /><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF/default.aspx">WPF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Xaml/default.aspx">Xaml</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/databinding/default.aspx">databinding</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/WPF_2F00_e/default.aspx">WPF/e</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/.NET+3.5/default.aspx">.NET 3.5</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Caliburn/default.aspx">Caliburn</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Featured/default.aspx">Featured</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/Silverlight/default.aspx">Silverlight</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/RIA/default.aspx">RIA</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MEF/default.aspx">MEF</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/MVVM/default.aspx">MVVM</category><category domain="http://devlicio.us/blogs/rob_eisenberg/archive/tags/UI+Architecture/default.aspx">UI Architecture</category></item></channel></rss>