First steps in Caliburn Micro with Windows Phone 8 – How to manage different DataContext

After a while I’m back to publish a post about Caliburn Micro and Windows Phone. The reason is that, during the development of my Movies Tracker app, I’ve found my self in a corner case I haven’t managed before: a ContextMenu. We’re talking about a control available in the Phone Toolkit, that can be used to add a contextual menu to a control. Windows Phone itself uses it widely: for example, when you press and hold your finger on an icon in the application list; or when you’re the People hub and you want to do some operations on a contact.

Usually ContextMenu is used in combination with a control that is used to display a collection, like a ListBox or LongListSelector: the user sees a list of items and can tap and hold on one of them to do some additional actions.

MoviesTracker1

Which is the problem in a MVVM application? That, in this case, we’re working with two different DataContext at the same time. Let’s see why:

  • The ListBox is placed inside a view, that will be connected to a specific ViewModel, that will take care of populating the collections, get the item selected by the user and stuff like that;
  • The ContextMenu is placed inside the ItemTemplate of the ListBox, since it’s applied to every single item of the list. This means that the DataContext of the ContextMenu control is different: inside an ItemTemplate the DataContext is represented by the object that is inside the collection (if you have a List<Person>, for example, the DataContext of the single item will be the Person class).

This means that, probably, you’ll define the actions to execute when the user taps on an item of the ContextMenu in the ViewModel of the page but the control won’t be able to see them, since it will expect to find them inside the Person object. And this is not good: defining methods inside a class that represents an entity is not a good idea; plus, probably the actions we’re going to execute (for example, deleting the selected item), will require us to interact with other properties of the ViewModel (like the collection), that can’t be accessed from the Person class.

Let’s see how to manage this scenario using Caliburn Micro.

Let’s start!

We’re going to use a simple scenario: an application to display a list of persons using a ListBox. By using a ContextMenu, we’ll give to the user the ability to delete a specific item. Let’s start with a standard Caliburn project: if you don’t know how to setup it, please refer to the other posts of the series. Our goal is to have one View with its specific ViewModel, connected together with the naming convention every Caliburn developer should be already familiar with.

First, we’re going to add to our project, using NuGet, the Phone Toolkit: simply right click on your project, choose Manage NuGet packages, search for and install the package called “phone toolkit”. Then, we add a new Person class, that we’re going to use to store the information about the persons. Since it’s a sample, it’s really simple:

public class Person
{
    public string Name { get; set; }
    public string Surname { get; set; }
}

Now we can define the View, inside the standard page MainPage.xaml: we’re going to include the ListBox control, with a simple ItemTemplate. We’ll simply display, in fact, name and surname of the person. Plus, we’re going to add the ContextMenu control to manage the contextual options:

<StackPanel>
    <ListBox x:Name="Persons">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <toolkit:ContextMenuService.ContextMenu>
                        <toolkit:ContextMenu>
                            <toolkit:MenuItem Header="delete" />                                                        
                        </toolkit:ContextMenu>
                    </toolkit:ContextMenuService.ContextMenu>
                    <TextBlock Text="{Binding Path=Name}" />
                    <TextBlock Text="{Binding Path=Surname}" />
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</StackPanel>

To use the ContextMenu you’ll need to add the toolkit’s namespace in your page declarations in the XAML:

xmlns:toolkit=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit”

First, we’re going to use the collections naming convention: since the name of the ListBox is Persons, we expect to have a collection with the same name in the ViewModel. This way, the data of the collection will be automatically displayed in the ListBox. The second thing to notice is that we’ve added the ContextMenu inside the StackPanel: this way the user will be able to tap and hold inside the item to display the menu. We’ve added just one action, using the MenuItem control: the deletion of the current item.

What we need to do when the user chooses the delete option?

  • We need to identify on which item the context menu has been activated;
  • We need to delete the item from the collection;

And here comes the problem I’ve described in the beginning of the post: we need to manage these operations in the ViewModel of the page (since it’s the one that contains the collection) but, since we’re inside the ItemTemplate, the application will look for them inside the Person object. Let’s introduce some Caliburn magic to solve our problem:

<phone:PhoneApplicationPage
    x:Class="Caliburn.ContextMenu.Views.MainPageView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
    xmlns:micro="clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True"
    x:Name="Page">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <ListBox x:Name="Persons">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel>
                                <toolkit:ContextMenuService.ContextMenu>
                                    <toolkit:ContextMenu>
                                        <toolkit:MenuItem Header="delete" 
                                                          micro:Action.TargetWithoutContext="{Binding ElementName=Page, Path=DataContext}"
                                                          micro:Message.Attach="[Event Tap] = [Action Delete($datacontext)]" />
                                    </toolkit:ContextMenu>
                                </toolkit:ContextMenuService.ContextMenu>
                                <TextBlock Text="{Binding Path=Name}" />
                                <TextBlock Text="{Binding Path=Surname}" />
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </StackPanel>
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>

I’ve included, this time, the whole XAML of the page for just one reason: please notice that I’ve assigned a name (using the x:Name property) to the page. Thanks to this name, I’m able to use a special attached property provided by Caliburn, called Action.TargetWithoutContext. It’s purpose is to change the DataContext of the action that we’re going to assign to the interaction: instead of using the default one (in this case, it would be the Person object) we can override it and specify a new one.  In our sample, we’re going to set the same DataContext of the page, that is our ViewModel: this is why we need to give to the entire page a name, so that we can refer to it to access to the DataContext property.

Now that the item is connected to the correct DataContext, we can define the action in the same way we’ve learned before: by using the Message.Attach attached property and setting first the event we want to manage (Tap) and then the method defined in the ViewModel to execute (Delete). You can notice something new: that we’re passing a parameter called $datacontext to the method. This way, we’re going to pass to the method the current DataContext, that is the selected Person object. This wasn’t needed when we simply had to manage the selected item in the list, thanks to the SelectedItem property of the ListBox control. This time, we can’t rely on it because, when we interact with another control in the ItemTemplate (like our ContextMenu or a Button) the SelectedItem doesn’t get a proper value, so we wouldn’t have a way to know which is the item the user is interacting with.

Thanks to this syntax, instead, we can pass the selected Person object to the method and work with it. To use both attached properties, you’ll need to declared the following namespace in your XAML’s page:

xmlns:micro=”clr-namespace:Caliburn.Micro;assembly=Caliburn.Micro”

And here is how it looks like our ViewModel:

public class MainPageViewModel : Screen
{
    private ObservableCollection<Person> persons;

    public ObservableCollection<Person> Persons
    {
        get { return persons; }
        set
        {
            persons = value;
            NotifyOfPropertyChange(() => Persons);
        }
    }

    public MainPageViewModel()
    {
        Persons = new ObservableCollection<Person>
            {
                new Person
                    {
                        Name = "Matteo",
                        Surname = "Pagani"
                    },
                new Person
                    {
                        Name = "John",
                        Surname = "Doe"
                    },
                new Person
                    {
                        Name = "Mark",
                        Surname = "White"
                    }
            };
    }

    public void Delete(Person person)
    {
        Persons.Remove(person);
    }

}

As you can see, the only difference with a standard action is that the Delete method accepts a parameter in input, which is the selected Person object: this way, we can simply remove it from the collection by calling the Remove method.

This approach isn’t useful just when you use a ContextMenu control, but every time you need to add another type of interaction with a ListBox rather than just selecting the item. I have another example of that in my Movies Tracker app: in the page used to search for a movie to add to your collection, I’ve included a button that works as “quick add”. The user can interact with a movie in the list in two ways: he can simply tap on one of them and being redirected to the detail page (and this is a standard interaction, made using the SelectedItem property of the list); or he can tap on the quick add button: in this case, I show a popup, where the user can set some options before saving it.

MoviesTracker2

This second scenario has the same problems we’ve seen with ContextMenu control: when the user taps on the button, I need to know which is the selected movie; and when the saving action is triggered, I need to execute a method declared in the ViewModel of the page, not in the Movie class, since it’s missing all the properties and classes I need to perform the operation. Same scenario, same solution: here is how it looks like the ItemTemplate of my movie list.

<DataTemplate x:Key="OnlineMoviesTemplate">
    <Grid Margin="0,0,0,12">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Image Width="99" Height="99" >
            <Image.Source>
                <BitmapImage UriSource="{Binding PosterThumbnailUrl}" CreateOptions="BackgroundCreation, DelayCreation" />
            </Image.Source>
        </Image>
        <StackPanel Margin="0,0,0,0" Grid.Column="1" VerticalAlignment="Top">
            <TextBlock FontSize="20"
                       FontWeight="ExtraBold"
                       Text="{Binding Title, Converter={StaticResource UppercaseConverter}}" TextWrapping="Wrap" TextAlignment="Left" />
        </StackPanel>
        <telerikPrimitives:RadImageButton RestStateImageSource="/Assets/Icons/addmovie.png" Grid.Column="2" HorizontalAlignment="Right"
                                          micro:Action.TargetWithoutContext="{Binding ElementName=Page, Path=DataContext}" micro:Message.Attach="[Event Click] = [Action AddMovie($datacontext)]" 
                                          />
    </Grid>
</DataTemplate>

As you can see, the code is exactly the same with seen for the ContextMenu: I’ve defined the Action.TargetWithoutContext and Message.Attach attached properties on the RadImageButton control so that, when the button is pressed, I execute the AddMovie method on the ViewModel of the page that contains the list. Thanks to the $datacontext syntax, I’m able to get in my method the movie the user has interacted with, so that I know which one to save. In this case, I’m using a RadImageButton (that is a Telerik control that is simply a button that, instead of being rendered using text, it uses an image) but it would have worked with any other control the user can interact with: a Button, a Checkbox, a RadioButton, etc.

In conclusion

The scenario described in this post isn’t so common: personally, I don’t suggest to abuse of the ContextMenu control, because it’s hard to discover for the user. But in case it happens (or you have to use another control, like happened to me with the button), these Caliburn Micro helpers will help you to save a lot of time and efforts.

Posted in Windows Phone | Tagged , , | 5 Comments

A new SQLite wrapper for Windows Phone 8 and Windows 8 – Relationships

This post is the second part of a series about a new SQLite wrapper for Windows Phone 8 and Windows 8, you can read the first part here.

One of the biggest flaws of the sqlite-net library for Windows 8 and Windows Phone 8 is that it doesn’t support relationships: there isn’t an attribute that can be used to mark a class property as a foreign key. Plus, sqlite-net offers some methods to manually execute a SQL statement, but the problem is that doesn’t offer a way to iterate through the results, but it always expects a specific object in return.

Let’s take a very common situation as example: to the database with the People  table we’ve created in the previous post we want to add a new table called Orders, to keep track of the orders made by the users. With sqlite-net we would have created two classes, one to map the People table and one to map the Orders table. Then, we could have execute a manual query in a similar way:

private async void OnExecuteJoin(object sender, RoutedEventArgs e)
{
   SQLiteAsyncConnection conn = new SQLiteAsyncConnection(Path.Combine(ApplicationData.Current.LocalFolder.Path, "people.db"), true);
   string query = "SELECT * FROM People INNER JOIN Orders ON Orders.PersonId = People.Id";
   List<Person> personOrders = await conn.QueryAsync<Person>(query);
}

Which is the problem with the sqlite-net approach? That, as you can see, when you call the QueryAsync() method it requires a <T> parameter, which is the type that you expect as a result of the query. Sqlite-net will automatically deserialize the result and will provide the object for you, ready to be used in your application. Smart, isn’t it? The problem is that this approach doesn’t work when we have a relationship: the sample code that you see is wrong, because when we have created a relationship between the tables People and Orders we don’t expect anymore to get, as a result, a Person object or an Order object, but a combination of both of them. The workaround, in this case, would be to create a third class, something like PeopleOrders, that will contain all the properties of the People class combined with the properties of the Orders class. Suddenly, it doesn’t sound so smart, isn’t it? Smile

With this new wrapper, instead, we’ll be able to support this scenario, because we can simply iterate trough the rows returned by the query and pick the data we need using the Statement object. The only downside is that we’ll have to do a lot of manual work: we’ll have to create our objects from scratch, since there is no automatic serialization and deserialization of the data.

Let’s see, step by step, how to support relationships with the new wrapper. We’ll reuse the knowledge we’ve learned in the previous post.

Let’s update the database

The first thing to do is to create a new table, that will store the new Orders table. Let’s see the code:

private async void OnCreateDatabaseClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "CREATE TABLE PEOPLE " +
                   "(Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                   "Name varchar(100), " +
                   "Surname varchar(100))";

    await database.ExecuteStatementAsync(query);
        string query2 = "CREATE TABLE ORDERS " +
                        "(Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                        "Description VARCHAR(200)," +
                        "Amount INTEGER," +
                        "PersonId INTEGER, " +
                        "FOREIGN KEY(PersonId) REFERENCES People(Id) ON DELETE CASCADE)";

        await database.ExecuteStatementAsync(query2);
}

The People table is the same we’ve seen in the previous post; the Orders table contains some columns to store the info about the order (description, amount, etc.) plus a column to manage the relationship, that will act as a foreign key. Specifically, we add a column called PersonId, that will store the id of the user that made the order taken from the Id column of the People table. We also define that this column is a foreign key and that, if we delete a user, all his orders will be deleted too (with the ON DELETE CASCADE statement). To define the key we use the following statement:

FOREIGN KEY(PersonId) REFERENCES People(Id)

that means that the PersonId column of the Orders table will hold a reference to the Id column of the People table.

Manage the orders

Now we’re ready to start using the relationships and add an order made by the user Matteo Pagani, which Id (that has been auto generated) is 1 (we’ve added this user using the code from the previous post).

private async void OnInsertOrderClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "INSERT INTO ORDERS(Description, Amount, PersonId) VALUES (@Description, @Amount, @PersonId)";
    Statement statement = await database.PrepareStatementAsync(query);
    statement.BindTextParameterWithName("@Description", "First order");
    statement.BindIntParameterWithName("@Amount", 200);
    statement.BindIntParameterWithName("@PersonId", 1);

    await statement.StepAsync();
}

If you’ve read my previous post, there should be nothing special in this code: we execute a insert query and we add, as parameters, the description of the order, the amount of the order and the id of the person that made the order. In the end, we execute the query using the StepAsync() method of the Statement object.

Now, it’s time to retrieve the data: let’s do a join statement, to retrieve all the orders with the information about the user that made it, like we’ve seen in the first sample with sqlite-net (the one that wasn’t working Smile).

private async void GetAllOrdersClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "SELECT * FROM ORDERS INNER JOIN PEOPLE ON ORDERS.PersonId=PEOPLE.Id";

    Statement statement = await database.PrepareStatementAsync(query);
    statement.EnableColumnsProperty();

    while (await statement.StepAsync())
    {
        MessageBox.Show(string.Format("{0} by {1} {2}", statement.Columns["Description"],
                                      statement.Columns["Name"], statement.Columns["Surname"]));
    }

}

The query is exactly the same: what changes is that, now, we’re able to iterate through the results so, thanks to the Statement object and the StepAsync() method, we’re able to extract all the values we need (Description, Name and Surname) and display it using a MessageBox. In a real application, probably, we would have populated a collection of data, that we would have displayed in the application using a ListBox or a LongListSelector, for example. Just notice that I’ve enabled the columns property feature (with the EnableColumnsProperty() method), so that we can access to the columns directly using their names as index of the Columns collection.

In the end

With the latest two posts we’ve seen a different approach to use SQLite in a Windows Phone 8 or Windows 8 app: with sqlite-net, we have an approach similar to the one we’ve learned with SQL CE in Windows Phone. Thanks to the power of LINQ, performing operations on database is really simple and, as with every other ORM, you can keep thinking using the objects approach, instead of having to deal with SQL. But all this flexibility comes with a price: the biggest limitation, right now, with sqlite-net, is that almost impossible to manage relationships. On the other side, with the new wrapper by Microsoft, you have full control, thanks to the great support to manual SQL statements; in complex applications, where you have to deal with lot of tables and relationships, it’s a big pro and it may help you a lot also to fine tuning performances; on the other side, you’ll have to deal on manual queries even for the most simple ones, like creating a table or adding some data. It’s up to you (and to the project you’re working on) to choose which wrapper is the best for you!

Posted in Windows 8, Windows Phone | Tagged , , | 6 Comments

A new SQLite wrapper for Windows Phone 8 and Windows 8 – The basics

One of the topics that gathered more attention on my blog is SQLite: developing an application without the need to store, somehow, the data locally is almost impossible, so developers are always searching the best way to achieve this objective. SQLite is one of the most interesting solutions out there, since it’s open source and it’s available for almost every platform on the market (mobile, web, client, etc.).

I’ve already talked you about sqlite-net, a library that is available for Windows Phone 8 and Windows 8 that can be used to perform operations on a SQLite database using a high level API that support LINQ operations. This library is very simple to use, but it has some limitations: the biggest one is that doesn’t support relationships out of the box.

Now Peter Torr (a member of the Windows Phone development team in Microsoft) with the support of Andy Wigley (a former Windows Phone Development MVP that now has joined Microsoft) have released on Codeplex a new SQLite wrapper, that is totally different from sqlite-net and that satisfies another type of approach: total control. In fact, this new wrapper doesn’t support any LINQ operation but only manual SQL statement: the biggest pro is that you can perform any type of operation, even managing relationships. The biggest cons is that you’ll have to rely on old plain SQL queries to do any operation, even the simplest ones, like creating a table or inserting some data.

Let’s see, step by step, how to use it and how the approach is different from using sqlite-net. In this first post we’re going to see the basics, in the next one we’ll talk about relationships.

Configure the wrapper

For the moment, since it’s written in native code, the library isn’t available on NuGet: you’ll have to download the source code from the Codeplex page. The solution contains two projects:  one is called SQLiteWinRT and the other one is called SQLiteWinRTPhone. The first one is for Windows Store apps, the second one for Windows Phone 8 apps (Windows Phone 7 is not supported, since it doesn’t support native code): you’ll have to add to your solution the project that fits your needs. For this tutorial I’m going to create a Windows Phone 8 application, so I’m going to use the second project. Plus, as we did for sqlite-net, we need to install the official SQLite runtime, that is available as a Visual Studio extension: here is the link for the Windows Store apps version, here, instead, is the link for the Windows Phone 8 version.

Now you’re ready to use it! We’re going to use the same sample we used in the sqlite-net post: a table to store data about people.

Create the database

Let’s see how to do it:

private async void OnCreateDatabaseClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "CREATE TABLE PEOPLE " +
                   "(Id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL," +
                   "Name varchar(100), " +
                   "Surname varchar(100))";

    await database.ExecuteStatementAsync(query);
}

First we create a new Database object, that we’re going to use to make operations on the database. There are various ways to instantiate it: in this sample we’re going to create it by specifying the folder in the isolated storage where to save the file and the file name. The folder is passed to the constructor using a StorageFolder object, which is the Windows Runtime class that identifies a folder in the isolated storage. In the sample, we’re simply using the storage’s root. If the database doesn’t exist, it will be created; otherwise it will simply be opened.

Then we can open the connection, by calling the OpenAsync() method: it accepts, eventually, a parameter to set the opening mode (like read only). If we don’t set it, it will be used the default one, that supports read and write operations.

Then, we go manual! As already anticipated, the wrapper doesn’t support LINQ operations, so you’ll have to write the needed SQL statements to perform the operation. I assume that you already know the basics of SQL, so I won’t describe in details the queries: in this sample we define a query to create a table called People with 3 columns: Id (which is the primary key and it’s an auto increment value), Name and Surname (which simply contains strings).

To execute the query we call the async method ExecuteStatementAsync() on the Database object, passing as parameter the string with the query statement. ExecuteStatementAsync() is the method we need to use when the query doesn’t return any value and when we don’t need to define any parameter (we’ll see later how to use them).

As you can see, there’s a huge difference with the sqlite-net approach: there’s no mapping with a class and there’s no automatic conversion to a table. Everything is made with plain SQL statements.

Perform operations on the database

The approach to perform operations (insert, update, select, etc.) is the same we’ve seen: we open the connection, we define the query statement and we execute the query. The only difference is that when you do an insert, for example, usually you need to set some parameters, because some elements of the query are not fixed but dynamic. For example, if we want to add a new row in the People table we’ve created in the step before, we need to pass two dynamic values: Name and Surname.

Here is the code to perform this operation:

private async void OnAddDataClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "INSERT INTO PEOPLE (Name, Surname) VALUES (@name, @surname)";
    Statement statement = await database.PrepareStatementAsync(query);
    statement.BindTextParameterWithName("@name", "Matteo");
    statement.BindTextParameterWithName("@surname", "Pagani");

    await statement.StepAsync();

    statement = await database.PrepareStatementAsync(query);
    statement.BindTextParameterWithName("@name", "John");
    statement.BindTextParameterWithName("@surname", "Doe");

    await statement.StepAsync();
}

Please enter the Statement class, that can be used to perform additional operations on the query, like adding parameters and iterating over the results. To prepare a Statement object, you’ll need to call the PrepareStatementAsync() method passing as parameter the query to execute. How to manage parameters? The simplest way is to use named parameters, which can be added to a query simply by prefixing the @ symbol to the name of the parameter. In the sample, the insert query accepts two parameters: @name and @surname.

How to define the value of these parameters? By calling the BindTextParameterWithName() method on the Statement object with two parameters: the first one is the name of the parameter, the second one is the value we want to assign. In the sample, we’re going to add two users to the table: one with name Matteo Pagani and one with name John Doe. To execute the query, we call the method StepAsync() on the Statement object. There are also other versions of the BindParameterWithName() method, according to the data type of the parameter (for example, if it’s a number you can use the method BindIntParameterWithName()).

But the StepAsync() method has another purpose: it can be used also to iterate through the results of the query, in case we’re performing a query that can return one or more values. Let’s see, for example, how to perform a select to retrieve the data we’ve just inserted:

private async void OnGetDataClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "SELECT * FROM PEOPLE";
    Statement statement = await database.PrepareStatementAsync(query);

    while (await statement.StepAsync())
    {
        MessageBox.Show(statement.GetTextAt(0) + " " + statement.GetTextAt(1));
    }
}

The first part of the code is the same we’ve seen before: we define the query (in this case, we retrieve all the rows of the People table), we prepare a Statement and we execute it with the StepAsync() method. The difference is that, this time, the StepAsync() method is performed into a while statement: it’s because the method will iterate over all the rows returned by the query so, every time we enter into the while loop, a new row is retrieved. In this sample, we expect to see the MessageBox twice: one for the user Matteo Pagani and one for the user John Doe. In the sample you see also how to get the values from the results: the Statement object offers some methods that starts with the Get prefix, that accepts as parameter the column index of the value to retrieve. There are some method for the most common data types: in this sample, since both Name and Surname are strings we use the GetTextAt() method, passing 0 as index to get the name and 1 as index to get the surname.

Of course we can combine what we’ve learned in the last two samples and, for example, we can perform a select query that contains some parameters:

private async void OnGetSomeDataClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "SELECT * FROM PEOPLE WHERE Name=@name";
    Statement statement = await database.PrepareStatementAsync(query);
    statement.BindTextParameterWithName("@name", "Matteo");

    while (await statement.StepAsync())
    {
        MessageBox.Show(statement.GetTextAt(0) + " " + statement.GetTextAt(1));
    }
}

In this sample, we retrieve from the People table only the rows where the column Name contains the value Matteo.

We have also another option to access to the columns of the rows we’ve retrieved with a query, but it’s disabled by default because it slower and it returns every value as string, instead of its proper type. To enable it you have to call the EnableColumnsProperty method of the Statement object: once you’ve done it, you can access to the  values by using the Columns property of the Statement object: it’s a collection and you can access to each item by using the column’s name as index. Here is a sample:

private async void OnGetSomeDataWithColumnsPropertyClicked(object sender, RoutedEventArgs e)
{
    Database database = new Database(ApplicationData.Current.LocalFolder, "people.db");

    await database.OpenAsync();

    string query = "SELECT * FROM PEOPLE";
    Statement statement = await database.PrepareStatementAsync(query);

    statement.EnableColumnsProperty();

    while (await statement.StepAsync())
    {
        MessageBox.Show(statement.Columns["Name"] + " " + statement.Columns["Surname"]);
    }
}

Coming soon

In this post we’ve learned the basic concepts to use this new wrapper to perform operations on a SQLite database and which are the differences with another popular wrapper, sqlite-net. In the next post we’ll see how to deal with relationships, one of the most problematic scenarios to manage nowadays. Meanwhile, you can play with the sample project.

Posted in Windows 8, Windows Phone | Tagged , , | 56 Comments

How to apply a background to a Panorama using binding

In the next few days I’m going to publish a new application called Movies Tracker, which can be used to keep track of the movies you’ve already seen or that you would like to see. The application is totally built with the MVVM pattern, using Caliburn Micro as framework. The application makes great use of the Panorama control: in the main page, I use it to display different movies categories; in the movie detail, I use it to display different information about the movie (the poster, the cast, the story, etc.). To give to the application a better look and feel, I’ve decided to use as a background of every Panorama an image taken from the movie, kindly provided by The Movie Database. And here comes the problem: since I’m using MVVM, the path of the image I want to display as background is available in the ViewModel, so I need to assign it as Panorama’s background using binding, like in the following sample:

<phone:Panorama>
    <phone:Panorama.Background>
        <ImageBrush ImageSource="{Binding Path=BackgroundImage}" />
    </phone:Panorama.Background>
           
    <phone:PanoramaItem Header="item 1" />
    <phone:PanoramaItem Header="item 1" />

</phone:Panorama>

Nothing strange right? So, which is the problem? That the above code simply doesn’t work: when you assign, in your ViewModel, an image path to the BackgroundImage property nothing happens. Unfortunately, the Panorama controls has a bug, so binding an image path to its Background property simply doesn’t work.

And here comes attached properties to the rescue! Attached properties is a powerful way to extend an existing control, provided by the XAML infrastructure: basically, you can add your custom property to an already existing control and you can decide the logic to apply when that property is set with a value. The workaround to this bug is to create an attached property, where we’re going to set the path of the image. When this value is set, we’re going to manually set the Background property of the control with the image from code: this way, everything will work fine, because the bug happens only when you use binding.

But we’re going to do more and overcome, at the same time, a limitation of the ImageBrush control: the ImageSource property, which contains the image path, supports only remote paths or local paths inside the Visual Studio project, so it’s ok to do something like in the following samples:

<phone:Panorama>
    <phone:Panorama.Background>
        <ImageBrush ImageSource="http://www.mywebsite.com/background.png" />
    </phone:Panorama.Background>
           
    <phone:PanoramaItem Header="item 1" />
    <phone:PanoramaItem Header="item 1" />

</phone:Panorama>

<phone:Panorama>
    <phone:Panorama.Background>
        <ImageBrush ImageSource="/Assets/Images/Background.png" />
    </phone:Panorama.Background>
           
    <phone:PanoramaItem Header="item 1" />
    <phone:PanoramaItem Header="item 1" />

</phone:Panorama>

What if the image is stored in the Isolated Storage? You can’t assign it using binding, but you’ll have to manually load in the code using a BitmapImage, like in the following sample:

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
{
    using (IsolatedStorageFileStream stream = store.OpenFile("Background.png", FileMode.Open))
    {
        BitmapImage image = new BitmapImage();
        image.SetSource(stream);
        ImageBrush brush = new ImageBrush
        {
            Opacity = 0.3,
            Stretch = Stretch.UniformToFill,
            ImageSource = image,

        };
        panorama.Background = brush;        
    }
}

The problem of this approach is that it works only in code behind, because you’ll need a reference (using the x:Name property) to the Panorama control: you can’t do that in a ViewModel. We’re going to support also this scenario in our attached property: if the image path is prefixed with the isostore:/ protocol, we’re going to load it from the isolated storage.

Let’s see the code of the attached property first:

public class BackgroundImageDownloader
{

    public static readonly DependencyProperty SourceProperty =
        DependencyProperty.RegisterAttached("Source", typeof(string), typeof(BitmapImage), new PropertyMetadata(null, callback));


    public static void SetSource(DependencyObject element, string value)
    {
        element.SetValue(SourceProperty, value);
    }

    public static string GetSource(DependencyObject element)
    {
        return (string)element.GetValue(SourceProperty);
    }

    private static async void callback(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Panorama panorama = d as Panorama;

        if (panorama != null)
        {
            var path = e.NewValue as string;
            {
                if (!string.IsNullOrEmpty(path))
                {
                    if (path.StartsWith("isostore:/"))
                    {
                        string localPath = path.Substring(10);
                        using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            using (IsolatedStorageFileStream stream = store.OpenFile(localPath, FileMode.Open))
                            {
                                BitmapImage image = new BitmapImage();
                                image.SetSource(stream);
                                ImageBrush brush = new ImageBrush
                                {
                                    Opacity = 0.3,
                                    Stretch = Stretch.UniformToFill,
                                    ImageSource = image,

                                };
                                panorama.Background = brush;        
                            }
                        }
                    }
                    else
                    {
                        BitmapImage image = new BitmapImage(new Uri(path, UriKind.Absolute));
                        ImageBrush brush = new ImageBrush
                        {
                            Opacity = 0.3,
                            Stretch = Stretch.UniformToFill,
                            ImageSource = image,

                        };
                        panorama.Background = brush;
                    }
                }
            }
        }
    }
}

We’ve defined a new property called Source, which can be used with a Panorama control: when a value is assigned to the property, the method called callback is executed and it contains two important parameters; the first one, d, which type is DependencyObject, is the control which the property has been attached to (in our case, it will always be a Panorama control); the second one, which type is DependencyPropertyChangedEventArgs, contains the value assigned to the property.

With these information we’ll be able to get a reference to the Panorama control which we want to apply the background to and the path of the image to load. We retrieve the path using the NewValue property of the DependencyPropertyChangedEventArgs  object and we check if it starts with isostore:/ or not. If that’s the case, we load the image from the Isolated Storage using the Storage APIs: once we get the image’s stream, we can create a new BitmapImage object and assign to it using the SetSource property. In the end, we create a new ImageBrush object and we assign the image as ImageSource: this way, we have a proper ImageBrush that we can assign to the Background property of the Panorama.

In case the image doesn’t come from the isolated storage, we simply create a new BitmapImage passing the Url, then we repeat the same operation as before: we create a new ImageBrush object, we assign the image as ImageSource and we set it as value of the Background property of the Panorama control.

How to use this attached property? First, we need to define in the XAML the namespace that contains our property (in the sample, I’ve called it panoramaBinding), than we can simply use the following code:

<phone:Panorama panoramaBinding:BackgroundImageDownloader.Source="{Binding BackgroundPath}">
    
    <phone:PanoramaItem Header="item 1" />
    <phone:PanoramaItem Header="item 2" />

</phone:Panorama>

Thanks to our attached property, BackgroundPath can be either a remote url or a local url: we just need to remember to add the isostore:/ prefix in the second case.

Here is a sample ViewModel where the BackgroundPath is set as a remote url:

public class MainViewModel : ViewModelBase
{
    private string backgroundPath;

    public string BackgroundPath
    {
        get { return backgroundPath; }
        set
        {
            backgroundPath = value;
            RaisePropertyChanged(() => BackgroundPath);
        }
    }

    public MainViewModel()
    {
        BackgroundPath = "http://4.bp.blogspot.com/-m0CqTN988_U/USd9rxvPikI/AAAAAAAADDY/4JKRsm3cD8c/s1600/free-wallpaper-downloads.jpg";
    }
}

And here’s another sample where I’ve defined a command, that is triggered when the user presses a button in the page: using  the new Windows Phone 8 APIs I copy some pictures in the isolated storage and then I set the BackgroundPath property using a local path:

public class MainViewModel : ViewModelBase
{
    private string backgroundPath;

    public string BackgroundPath
    {
        get { return backgroundPath; }
        set
        {
            backgroundPath = value;
            RaisePropertyChanged(() => BackgroundPath);
        }
    }

    public RelayCommand LoadImages
    {
        get
        {
            return new RelayCommand(async () =>
                {
                    StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync("Assets\\Images\\");
                    IReadOnlyList<StorageFile> files = await folder.GetFilesAsync();
                    foreach (StorageFile file in files)
                    {
                        await file.CopyAsync(ApplicationData.Current.LocalFolder, file.Name, NameCollisionOption.ReplaceExisting);
                    }

                    BackgroundPath = "isostore://Balls.jpg";
                });
        }
    }
}

In both cases the result will be what you expect: the image will be displayed as background of the Panorama control. However, be aware that loading too big images can lead to many performance issues, since they can consume a lot of memory. But we’ll talk about this in another post Smile

In the meantime, you can play with the sample project!

Posted in Windows Phone | Tagged , | 9 Comments

Telerik and Windows Phone 8 – The JumpList (Multi selection)

We continue our journey to see how to use some of the most interesting features of the RadJumpList, one of the available controls in the RadControls for Windows Phone toolkit developed by Telerik.

Multi selection

Multi selection is a simple but interesting feature that will allow the user to choose more than one element from the list, by checking the checkboxes that are displayed on the left of the item. By default, selection isn’t enabled: the RadJumpList control will behave like a standard list; when the user taps on an item, you can intercept it and implement your own logic (for example, you can redirect the user to a detail page to see the details of the selected item.

The first step to enable it is to set the IsCheckModeEnabled property to True and you can do it in the XAML or in the code. Once it’s enabled, you’ll notice that the left margin of the items will be greater, but the list will continue to work as usual.

You have two ways to effectively enable multi selection mode:

  • You can tap on the left of any item: multi selection will be activated and you’ll see the checkboxes appear.
  • You can set the IsCheckModeActive property of the RadJumpList control to True: this way, you can also enable the multi select mode in the code if, for example, you want to provide a button for this purpose. The native Mail app shows an example of this behavior: you can enable multi select mode by tapping on the left of any item or by using the appropriate button in the Application Bar.

By default, if you’ve enable grouping like we’ve seen in the previous post, user will be allowed also to select groups and not only single items. If you want to disable this behavior, you need to set the GroupCheckMode to None: this way, checkboxes will be displayed only next to the single items.

Here is a sample of a RadJumpList control with multi selection enabled:

<telerikDataControls:RadJumpList x:Name="People" IsCheckModeEnabled="True" GroupCheckMode="None">
    <telerikDataControls:RadJumpList.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Path=Name}" />
                <TextBlock Text="{Binding Path=Surname}" />
            </StackPanel>
        </DataTemplate>
    </telerikDataControls:RadJumpList.ItemTemplate>
</telerikDataControls:RadJumpList>

Managing the selected items is really simple: the RadJumpList control exposes a property called CheckedItems, which contains the collection of items that have been selected. Here is a really sample code that can be used to show the number of items that have been selected by the user.

private void OnShowItemsClicked(object sender, RoutedEventArgs e)
{
    MessageBox.Show(People.CheckedItems.Count.ToString());
}

Supporting multi selection with MVVM

One issue of the RadJumpList control is that, at the moment, CheckedItems doesn’t support binding, so you can’t have a property in your ViewModel with the collection of the items that have been selected. The best workaround I’ve found and that I’m using in my Speaker Timer app is to use a custom behavior, that has been developed by my dear friend Marco Leoncini. The purpose of this behavior is to automatically store, in a property of the ViewModel, the list of selected items.

First, you need to define in your ViewModel a collection, that will hold the items that will be checked by the user. For the following samples, I’m going to use the helpers provided by the MVVM Light Toolkit by Laurent Bugnion, that you can install using NuGet. Here is a ViewModel sample:

public class MultiSelectViewModel : ViewModelBase
{
    private ObservableCollection<Person> people;

    public ObservableCollection<Person> People
    {
        get { return people; }
        set
        {
            people = value;
            RaisePropertyChanged("People");
        }
    }

    private ObservableCollection<Person> itemsToDelete;

    public ObservableCollection<Person> ItemsToDelete
    {
        get { return itemsToDelete; }
        set
        {
            itemsToDelete = value;
            RaisePropertyChanged("ItemsToDelete");
        }
    }


    public MultiSelectViewModel()
    {
        ItemsToDelete = new ObservableCollection<Person>();
    }
}

In this sample, ItemsToDelete is the property that will store the items selected by the user (this sample is taken from my Speaker Timer app, where multi selection is enabled to delete one or more sessions). The second step is to create a new class, that will contain our behavior:

public class AddoToCheckedItemBehavior : Behavior<RadDataBoundListBox>
{
    public AddoToCheckedItemBehavior() { }

    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.ItemCheckedStateChanged += AssociatedObject_ItemCheckedStateChanged;
    }

    void AssociatedObject_ItemCheckedStateChanged(object sender, ItemCheckedStateChangedEventArgs e)
    {
        var viewModel = ((FrameworkElement)sender).DataContext as MainPageViewModel;
        if (viewModel == null) return;
        if (e.IsChecked)
        {
            viewModel.ItemsToDelete.Add(((Telerik.Windows.Data.IDataSourceItem)e.Item).Value as Session);
        }
        else { viewModel.ItemsToDelete.Remove(((Telerik.Windows.Data.IDataSourceItem)e.Item).Value as Session); }
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.ItemCheckedStateChanged -= AssociatedObject_ItemCheckedStateChanged;
    }
}

The purpose of this behavior is very simple: it inherits from the Behavior<RadJumpList> class (so that it can be used in combination with a RadJumpList control) and it subscribes to the ItemCheckedStateChanged event, that is triggered every time the user checks or unchecks an item from the list. When this event is triggered, we get a reference to the current ViewModel and we add or remove the selected item from the ItemsToDelete collection. To do this, we use a property returned by the event handler’s parameter: the e object (which type is ItemCheckedStateChangedEventArgs) contains the properties Item (which is the selected item) and IsChecked (which is a boolean, that tells you if the item has been checked or unchecked).

There’s space for improvements in this behavior: one limitation is that it works just for our specific ViewModel, since when we get the reference to the ViewModel associated to the current view (using the DataContext property) we cast it to the MainViewModel class. If we need to apply the same behavior to multiple RadJumpList controls in different page, we can create a base class which our ViewModels can inherit from. This base class will host the the ItemsToDelete property, so that every ViewModel will be able to use it. This way, we can change the cast from MainViewModel to our new base class and reuse the same behavior for different ViewModels.

How to apply the behavior? First, we need to add a reference to the System.Windows.Interactivity library, that is available by clicking with the right click on your project and choosing Add new reference: you’ll find it in the Assemblies, Extensions sections.

After that, you can add the behavior directly in the XAML, by declaring the following namespace (plus the namespace of the behavior’s class you’ve created):

xmlns:i=”clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity”

<telerikDataControls:RadJumpList IsCheckModeEnabled="True" GroupCheckMode="None" ItemsSource="{Binding Path=People}">
    <telerikDataControls:RadJumpList.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <TextBlock Text="{Binding Path=Name}" />
                <TextBlock Text="{Binding Path=Surname}" />
            </StackPanel>
        </DataTemplate>
    </telerikDataControls:RadJumpList.ItemTemplate>
    <i:Interaction.Behaviors>
        <behaviors:AddoToCheckedItemBehavior />
    </i:Interaction.Behaviors>
</telerikDataControls:RadJumpList>

Now in the ViewModel, automatically, the ItemsToDelete property will always contain the items that have been checked by the user, so that you can use them for your own needs. In the following sample, we define a command to simply show a message with the number of selected items:

private RelayCommand showCount;

 public RelayCommand ShowCount
 {
     get
     {
         if (showCount == null)
         {
             showCount = new RelayCommand(() =>
                                              {
                                                  MessageBox.Show(ItemsToDelete.Count.ToString());
                                              });
         }
         return showCount;
     }
 }

Happy coding! As usual, remember that the sample project doesn’t contain the Telerik libraries, since we’re talking about a commercial suite.

Posted in Windows Phone | Tagged , | 6 Comments