Category Archives: Windows Phone

[WP7] Handling events in the items of a ListBox (Windows Developer Show podcast challenge)

Ryan, I you read this, please shout a small advert for my 2Day todo-list application, thanks 😀

Tonight while listening to the Windows Developer Show podcast, a nice challenge came up as a listener had a question about usage of events in a ListBox on the Windows Phone platform. Ryan had the good idea to suggest that a listener could write a blog post before the end of the show to help this guy, and here we are 🙂

Background

In the sample app, because of lack of time, I go straight to the point. In the XAML, I have a ListBox databound to an ObservableCollection. I use code-behind and I’m not using MVVM pattern but for the point of this article, I guess it’s good enough. So here is the XAML:


    
        
            
                
            
        
    

and here is the code-behing:

public partial class MainPage : PhoneApplicationPage
{
    private readonly ObservableCollection dataSource;

    public MainPage()
    {
        this.InitializeComponent();

        this.dataSource = new ObservableCollection { new Item { Name = "Ryan" }, new Item { Name = "Travis" }, new Item { Name = "Jeremy " } };

        // no MVVM for this sample...
        this.DataContext = this;
    }

    public ObservableCollection DataSource
    {
        get { return this.dataSource; }
    }
}

public class Item 
{
    public string Name { get; set; }
}

Wiring events

So now the question is: how I can use events for the items inside the ListBox. Here are the options you have:

Options 1: use event handlers

The idea is just to setup an event handler in the XAML of the DataTemplate. Here is the XAML:


    
        
            
                
            
        
    

and here is the associated C#:

private void Border_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
    // option 1
    // sender is the Border
    // navigate the visual tree up to find the ListBoxItem if needed
    // datacontext is the instance of the Item objects
}

Option 2: use commands

Another option is to use command which is very common for MVVM apps. The trick you might need is to wire an command on something that is not a button. But the problem is that it’s the Button type which has a Command property. A possible trick is to style the button to make it looks like a standard control, here is an example:


    
        
    
                 
    
        
            
                
            
        
    

Option 3: use attached properties

Another option, use attached properties. See this blog post about the way to achieve that. The blog post is old and targets WPF but the same principles are valid for a Windows Phone 7 app.

Option 4: use MVVM Light’s EventToCommand

MVVMLight is a very nice MVVM framework. EventToCommand is an extension of the previously described attached properties and can help you attach a command to an event.

Hope it helps 🙂

SQL database version management in a Windows Phone 7 application

This is the second tips’n’tricks post talking about the stuff I discover while working on the 2Day todo-list application for Windows Phone. In my last blog post I talked about random ArgumentException. This time, I’m talking about the way to handle version management in SQL database in a Windows Phone 7 app.

As soon as you want to push an update to an existing app using a SQL database you will have to deal with version management. The basic idea is that you might want to alter the schema of the database (for examples by adding tables or columns) while not breaking compatibility for your existing users. You must therefore be able to upgrade your database from version N to version N + 1.

On the Windows Phone platform, this is done using the DatabaseSchemaUpdater class. You can get an instance of this type using the CreateDatabaseSchemaUpdater() method of your DatabaseContext. You can then change the database by using the AddTable and AddColumn methods. You can retrieve the version of the database by using the DatabaseSchemaVersion property.  Simple, isn’t it ?

Here are some tips to update your database properly:

  • define all your update operations in a single class – it will be easier for you to manage future updates
  • define the current version of your database using a constant in your class – check this constant agains the DatabaseSchemaVersion property to determine if you must perform an upgrade
  • handle incremental update, when you push an update for version 3, you can still have users with version 1 or 2, so handle upgrade from 1 to 2 and from 2 to 3 incrementally
  • when you add new column to an existing table, the type of this colum must be nullable (bool?, string?, etc.)

Here is what the code looks like in 2Day:

using Japf.ToDo.Core.Model;
using Microsoft.Phone.Data.Linq;

namespace Japf.ToDo.Core.IO
{
    public class DatabaseVersion
    {
        // database history
        // v0. Feb. 20th 2011 first version
        // v1. May. 7th 2012 add the SpecialFolders table
        // v2. May. 19th 2012 add the Progress column in the Task table
        // v3. Auguest. 12th 2012 add the IsFocused column in the Folders & SpecialFolders table
        public const int Version = 3;

        public static void UpgradeIfNeeded(DatabaseContext context)
        {
            DatabaseSchemaUpdater dbUpdater = context.CreateDatabaseSchemaUpdater();
            if (dbUpdater.DatabaseSchemaVersion < Version)
            {
                // handle update for user with version 0
                if (dbUpdater.DatabaseSchemaVersion == 0)
                {
                    From0To1(context);
                    From1To2(context);
                    From2To3(context);
                }
                // handle update for user with version 1
                else if (dbUpdater.DatabaseSchemaVersion == 1)
                {
                    From1To2(context);
                    From2To3(context);
                }
                // handle update for user with version 2
                else if (dbUpdater.DatabaseSchemaVersion == 2)
                {
                    From2To3(context);
                }
            }
        }

        private static void From0To1(DatabaseContext context)
        {
            var dbUpdater = context.CreateDatabaseSchemaUpdater();

            // add a new table containing where each row is a SpecialFolder
            dbUpdater.AddTable();

            // add a column to the existing table Folder named ShowInSpecialFolders
            dbUpdater.AddColumn("ShowInSpecialFolders");

            // update the version of the schema
            dbUpdater.DatabaseSchemaVersion = 1;

            // send the changes to the db
            dbUpdater.Execute();

            // do not reuse the DatabaseSchemaUpdater for other update as it still contains
            // instructions to add the new table and the new column
        }

        // other methods omitted for clarity...
    }
}

Hope it helps 🙂

Random ArgumentException in a Windows Phone 7 application

While working on the last update of the 2Day todo-list application for Windows Phone, I encountered a strange bug I wanted to share in this post. The symptoms were very awkward: an ArgumentException where thrown randomly while using the app:

As always when I got that kind of stuff, I try to find out a reproducible set of actions which lead to the crash. Unfortunately in this case it wasn’t that easy.

After a couple of try, I found out I could reproduce the problem by doing the same set of actions many times:

  • launch 2Day
  • navigate to the details view of a task
  • go back to the home screen
  • navigate to the details view of another task
The crash then happened between 1 and 20 tries. The stacktrace wasn’t very helpful:
at MS.Internal.XcpImports.CheckHResult(UInt32 hr)
at MS.Internal.XcpImports.Collection_AddValue[T](PresentationFrameworkCollection`1 collection, CValue value)
at MS.Internal.XcpImports.Collection_AddDependencyObject[T](PresentationFrameworkCollection`1 collection, DependencyObject value)
at System.Windows.PresentationFrameworkCollection`1.AddDependencyObject(DependencyObject value)
at System.Windows.Controls.UIElementCollection.AddInternal(UIElement value)
at System.Windows.PresentationFrameworkCollection`1.Add(UIElement value)
at System.Windows.Controls.ItemsControl.AddVisualChild(Int32 index, DependencyObject container, Boolean needPrepareContainer)
at System.Windows.Controls.ItemsControl.AddContainers()
at System.Windows.Controls.ItemsControl.RecreateVisualChildren(IntPtr unmanagedObj)
at MS.Internal.XcpImports.MeasureOverrideNative(IntPtr element, Single inWidth, Single inHeight, Single& outWidth, Single& outHeight)
at MS.Internal.XcpImports.FrameworkElement_MeasureOverride(FrameworkElement element, Size availableSize)
at System.Windows.FrameworkElement.MeasureOverride(Size availableSize)
at Microsoft.Phone.Controls.Pivot.MeasureOverride(Size availableSize)
at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight)
After some time spend on the Internet, I found out this post on StackOverflow. It basically told me something could be wrong with the naming of the elements in the XAML. Actually I did change some XAML in 2Day in order to change the layout of the task create/edit page:
During that refactoring I changed the way the notes are displayed and I created a UserControl for that purpose. Ultimately, I found out that this control was named: it has a x:Name set at the top of the XAML (note the line 8 in the following sample):

I needed that because I wanted to databind the Text property of a TextBox on a Dependency Property defined on the control itself:

Because the post on StackOverflow talked about naming controls, I thought that could be the cause of the error. It it was actually ! Removing this single piece of XAML (and changing the binding a little bit) removed the crash from the app !

This is definitively the strangest bug I’ve seen on the Windows Phone platform… Hope it helps 🙂

If you want to give a try to a fast & fluid todo-list app for Windows Phone 7, feel free to download 2Day: