Navigating in Windows Phone 7 using Caliburn Micro

Everything must be shocking to new developers who haven’t used a framework and has been following the traditional way of developing applications in Windows Phone 7.

In this post, I will teach you how to code from Traditional way to Caliburn Micro way.

Assuming we have a MainPage.xaml which contains a button that just simply navigates us from MainPage to Page1.xaml.

The basic way to do this is by adding a click event on our button and then saying that

NavigationService.Navigate(new Uri(“/Page1.xaml”, UriKind.Relative));

in Caliburn Micro, since the PhoneApplication Class is abstracted away from us, we have no idea if its still the same. Our bootstrapper is inheriting from it and assuming we registered our ViewModel in our IoC Container, then we could probably say that,

public void GotoPageTwo() {
navigationService.UriFor<PivotPageViewModel>()
.WithParam(x => x.NumberOfTabs, 1)
.WithParam(y => y.PageName, “leo”)
.Navigate();
}

So what benefit did I get, not only was the code readable but it has a extension methods that can support lambda expressions which we cannot do in traditional way. We could have a longer line of code just to pass a parameter. And did I forgot to mention that you don’t need to do much Binding your your commands? I think I did not, but like I said, before you need to either brute force and just double click the button or create a property and bind a command into it.

In Caliburn Micro, I could just simply say

<Button x:Name=”GoToPageTwo” />

and behind the scenes, it automatically binds the command whether its a delegate or composite command it is supported.

 

Creating your first Windows Phone 7 with Caliburn Micro

Caliburn Micro is a small, yet powerful framework designed for WPF, Silverlight and WP7. It implements a variety of UI patterns for solving real-world problems. Patterns that are highlighted include MVVM (Presentation Model), MVP and MVC.

It’s “Convention over configuration” helps you build rapid application development faster , clean code and easy to data bind.

More on this can be find in this website : http://caliburnmicro.codeplex.com/

In traditional programming, most of us will be doing the application stuff layer like tombstoning, navigation exception, startup URIs in the App.xaml.cs. but if you are used to using a Bootstrapper then you might be surprised let’s say Caliburn Micro that if you use this framework, the App.xaml.cs will now be just this

public partial class App : Application

    {

        public App()

        {

            InitializeComponent();

        }

    }

So, where did this 100 lines of code went from? Because even in App.xaml, we’re going to remove the default code that adds the 4 States of the Phone (Launching, Activated, Deactivated, Closing) and chance it to this

<Application.Resources>
<local:Bootstrapper x:Key=”bootstrapper” />
</Application.Resources>

Now, we create a new class in our project, and let’s call it the Bootstrapper. This Bootstrapper is from Caliburn Micro and this framework automatically binds your properties to your View AND you can easily bind Commands to your controls!

public class Bootstrapper : PhoneBootstrapper
{
private PhoneContainer _container;
protected override void OnLaunch(object sender, Microsoft.Phone.Shell.LaunchingEventArgs e)
{
base.OnLaunch(sender, e);
}

protected override void Configure()
{
_container = new PhoneContainer(RootFrame);

_container.RegisterPhoneServices();

// _container.PerRequest<MainPageViewModel>();
AddCustomConventions();
}

static void AddCustomConventions()
{
ConventionManager.AddElementConvention<Pivot>(Pivot.ItemsSourceProperty, “SelectedItem”, “SelectionChanged”).ApplyBinding =
(viewModelType, path, property, element, convention) =>
{
if (ConventionManager
.GetElementConvention(typeof(ItemsControl))
.ApplyBinding(viewModelType, path, property, element, convention))
{
ConventionManager
.ConfigureSelectedItem(element, Pivot.SelectedItemProperty, viewModelType, path);
ConventionManager
.ApplyHeaderTemplate(element, Pivot.HeaderTemplateProperty, viewModelType);
return true;
}

return false;
};

ConventionManager.AddElementConvention<Panorama>(Panorama.ItemsSourceProperty, “SelectedItem”, “SelectionChanged”).ApplyBinding =
(viewModelType, path, property, element, convention) =>
{
if (ConventionManager
.GetElementConvention(typeof(ItemsControl))
.ApplyBinding(viewModelType, path, property, element, convention))
{
ConventionManager
.ConfigureSelectedItem(element, Panorama.SelectedItemProperty, viewModelType, path);
ConventionManager
.ApplyHeaderTemplate(element, Panorama.HeaderTemplateProperty, viewModelType);
return true;
}

return false;
};
}

protected override object GetInstance(Type service, string key)
{
return _container.GetInstance(service, key);
}

protected override IEnumerable<object> GetAllInstances(Type service)
{
return _container.GetAllInstances(service);
}

protected override void BuildUp(object instance)
{
_container.BuildUp(instance);
}
}

Now, the next question for you guys is, how will you now handle tombstoning your applications? If you notice that there this Bootstrapper must Inherit from the PhoneBootStrapper class, and what does it contain?

public class PhoneBootstrapper : Bootstrapper
{
private bool phoneApplicationInitialized;
private PhoneApplicationService phoneService;

public PhoneApplicationFrame RootFrame { get; private set; }

public PhoneBootstrapper()
: base(true)
{
}

protected override void PrepareApplication()
{
base.PrepareApplication();
this.phoneService = new PhoneApplicationService();
this.phoneService.add_Activated(new EventHandler<ActivatedEventArgs>(this.OnActivate));
this.phoneService.add_Deactivated(new EventHandler<DeactivatedEventArgs>(this.OnDeactivate));
this.phoneService.add_Launching(new EventHandler<LaunchingEventArgs>(this.OnLaunch));
this.phoneService.add_Closing(new EventHandler<ClosingEventArgs>(this.OnClose));
this.Application.ApplicationLifetimeObjects.Add((object) this.phoneService);
if (this.phoneApplicationInitialized)
return;
this.RootFrame = this.CreatePhoneApplicationFrame();
((Frame) this.RootFrame).add_Navigated(new NavigatedEventHandler(this.OnNavigated));
this.phoneApplicationInitialized = true;
}

private void OnNavigated(object sender, NavigationEventArgs e)
{
if (this.Application.RootVisual == this.RootFrame)
return;
this.Application.RootVisual = (UIElement) this.RootFrame;
}

protected virtual PhoneApplicationFrame CreatePhoneApplicationFrame()
{
return new PhoneApplicationFrame();
}

protected virtual void OnLaunch(object sender, LaunchingEventArgs e)
{
}

protected virtual void OnActivate(object sender, ActivatedEventArgs e)
{
}

protected virtual void OnDeactivate(object sender, DeactivatedEventArgs e)
{
}

protected virtual void OnClose(object sender, ClosingEventArgs e)
{
}
}

So the PhoneBootstrapper abstracted away the original App.xaml.cs and we now just inherit it. If we ever wanted to handle these states therefore, we could just say in our Bootstrapper to override these methods.

Next, what’s the best thing about this is it automatically binds your ViewModel to your Views without having to manually implement dependency injection. Basically, if you have a MainPageView.xaml, and you created a MainPageViewModel then the caliburn micro should automatically inject the ViewModel to the View or from the View to the ViewModel which is normally called as ViewModel First or View First approach.

Next, how do we then bind our ViewModel properties to our View controls? The traditional way would be saying {Binding Path=FirstName}. In caliburn micro you don’t do it that way. You just say <TextBlock x:Name=”FirstName”/> and it will automatically bind the property name FirstName from the ViewModel. All the traditional ways are being abstracted away from us making it simplier to code and develop applications in WPF, Silverlight or Windows Phone 7. This is why the Framework’s slogan is “Convention over configuration”, so you are still doing MVVM but those manually long codes is now handled behind the scenes. It’s just like saying you are a new developer and you don’t know where to start. Most of the people before preferred to code in Visual Basic because its easy to use and most of the common things that have to be code are already handled by the Visual Basic. Same goes with this framework, if you are new to MVVM and would like to develop an application but want to make sure you are following the MVVM Pattern, then this framework is for you.