Siguiendo con el post anterior os explicaré algunos detalles de Caliburn.Micro que son muy útiles y nos pueden ahorrar bastante tiempo. Además veremos cómo navegar entre distintas pantallas de nuestra aplicación.

Partiendo del ejemplo de la primera parte vamos a añadirle más funcionalidades. En la página que ya teníamos le añadiremos un campo de texto y un botón, este botón sólo estará activo cuando escribamos en el campo de texto la palabra jesus. Una vez que el botón se active lo podremos pulsar y navegaremos a una nueva pantalla donde tendremos una lista de elementos.

Vamos a ir paso a paso, lo primero de todo va a ser añadirle un campo de texto y un botón a nuestra página MainPageView.xaml. El xaml nos va a quedar algo parecido a esto:

<Page
    x:Class="CaliburnMicroW10.Views.MainPageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="50"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <TextBlock x:Name="Title" Grid.Row="0" HorizontalAlignment="Center"/>
        <TextBox x:Name="Name" Grid.Row="1" Margin="0 10 0 0"/>
        <Button x:Name="Navigate" Grid.Row="2" Content="Navegar" HorizontalAlignment="Center" Margin="0 10 0 0"/>
    </Grid>
</Page>

Hasta este punto no hay nada raro y realmente puedes utilizar otro tipo de layout ya que es un ejemplo muy simple. Lo interesante viene cuando vamos a nuestro view model, en él vamos a crear dos propiedades: Name de tipo string y CanNavigate de tipo bool.

Si te fijas bien verás que el nombre de la primera propiedad coincide con el nombre de nuestro campo de texto x:Name="Name", de esta forma conseguiremos que todo lo que escribamos en el campo de texto quede almacenado en la propiedad gracias al binding que hace Caliburn por nosotros. La siguiente propiedad tiene el mismo nombre que nuestro botón x:Name="Navigate" pero con el prefijo Can añadido delante de ella y además es de tipo bool, con esto lo que vamos a conseguir es que la propiedad IsEnabled de nuestro botón este bindeada a esta propiedad por lo que si la propiedad es true nuestro botón estará activo y si es false pues lo contrario. De esta forma nuestro view model quedará más o menos así:

private string _name = String.Empty;

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        NotifyOfPropertyChange(() => CanNavigate);
    }
}

public bool CanNavigate
{
    get { return Name.Equals("jesus"); }
}

Si te fijas verás que le hemos añadido algo más de código a nuestras propiedades. En el set de Name hemos llamado al NotifyOfPropertyChange que nos provee Caliburn para que la vista vuelva a evaluar la propiedad CanNavigate. Dentro de esta propiedad le hemos añadido que el valor que debe devolver debe de ser true cuando Name sea igual a jesus. Con este par de líneas hemos conseguido la funcionalidad que deseábamos con bastante menos código del que hubiésemos necesitado sin la ayuda de Caliburn.

A continuación vamos a añadir lo necesario para poder navegar a una nueva página. Lo primero por supuesto va a ser crear la nueva página, en este caso se va a llamar SecondPageView.xaml y su view model correspondiente SecondPageViewModel.cs los cuales vamos a dejar en blanco de momento, no se nos debe de olvidar añadir este view model a nuestro inyector de dependencias al igual que hicimos con el primer view model. Para poder manejar el evento de click del botón añadimos un nuevo método público en nuestro view model con el mismo nombre que nuestro botón public void Navigate(), al tener el mismo nombre, Caliburn ejecutará el método con el evento onClick del botón.

Para poder realizar la navegación necesitamos tener acceso a INavigationService, por ello vamos a añadir un constructor a nuestro view model y le vamos a poner como parámetro INavigationService, de esta forma vamos a conseguir que el inyector de dependencias resuelva INavigationService y nos provea una instancia del mismo para usarla en nuestro view model. De esta forma el constructor va a quedar así:

private readonly INavigationService _navigationService;

public MainPageViewModel(INavigationService navigationService)
{
    _navigationService = navigationService;
}

Para navegar vamos a utilizar el método NavigateToViewModel de la siguiente manera:

public void Navigate()
{
    _navigationService.NavigateToViewModel<SecondPageViewModel>();
}

Si queremos pasar algún parámetro a la nueva página podremos hacerlo pasándolo como parámetro de este método. Si ejecutamos la aplicación en este punto debemos de poder escribir ya jesus en el campo de texto y navegar a la nueva página.

Lo siguiente que vamos a hacer es añadir la lista de elementos a nuestra nueva página, para ello utilizamos el componente ListView, que de una manera sencilla nos permite añadir una lista:

<Page
    x:Class="CaliburnMicroW10.Views.SecondPageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView x:Name="Items"/>
    </Grid>
</Page>

A continuación vamos a nuestro view model y añadimos una nueva propiedad llamada Items de tipo ObservableCollection:

public class SecondPageViewModel : Screen
{
    public ObservableCollection<string> Items
    {
        get
        {
            return new ObservableCollection<string>(new[] { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 9", "Item 10", "Item 11", "Item 12" });
        }
    }
}

Y ya está, ya tenemos una lista en nuestra nueva pantalla. Aunque parezca mentira esto es todo, Caliburn hará el trabajo de binding ya que hemos llamado de la misma manera nuestra lista x:Name="Items" que la propiedad de nuestro view model. Ahora vamos a dar un paso más, ya que la mayor parte de las veces que añadimos una lista lo que queremos es que el usuario escoja uno de los elementos, necesitamos saber cual es el elemento que ha sido pulsado. Como podrás imaginar esto también es muy fácil. Lo único que tenemos que hacer es añadir una nueva propiedad en nuestro view model SelectedItem de tipo string y Caliburn se encargará de asignarle el valor del item seleccionado.

public string SelectedItem
{
    get { return _selectedItem; }
    set
    {
        _selectedItem = value;
        new MessageDialog(_selectedItem).ShowAsync();
    }
}

En este ejemplo lo que hacemos es mostrar un diálogo con el valor del item seleccionado, pero podríamos hacer lo que fuese necesario según la funcionalidad de nuestra aplicación.

Con este par de posts creo que es suficiente para poder empezar a trabajar con Caliburn.Micro en nuestras aplicaciones universales de Windows 10. Si quieres profundizar más te recomiendo el blog de Matteo Pagani (en inglés) en el que puedes encontrar toda una serie de artículos explicando Caliburn en profundidad, a pesar de estar escritos para Windows Phone 8 muchas cosas siguen siendo igualmente válidas a día de hoy.

Como siempre, puedes encontrar todo el código del ejemplo en mi GitHub desde donde lo puedes descargar, probar y modificar sin ningún problema.