Converting from Silverlight To Universal Apps – MVVM, ListView and Commands

Converting a Windows Phone Silverlight app to a Universal WinRT app isn’t straight forward, and it’s hard to Google for answers. I converted one of my not too advanced apps to universal Windows/Phone and here are some of the things I had to do. The quick-list for Xaml changes is here.

I’m using MVVMLight because it makes it so much easier to develop apps. When developing the Silverlight app I used Interation.Triggers and EventTrigger/EventToCommand to fire off commands in my ViewModel from clicked ListBox items. When converting to universal/winrt I ran into problems with referencing the Microsoft.Expression.Interactions assemblies for the Windows and Windows Phone projects so I decided to code up a simple ItemClickCommand instead which uses an attach property on the ListView. Based (more or less a replica) on the code by Marco Minerva, the command-class looks like this:

public static class ItemClickCommand
{
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.RegisterAttached("Command", typeof (ICommand),
            typeof (ItemClickCommand), new PropertyMetadata(null, OnCommandPropertyChanged));

    public static void SetCommand(DependencyObject d, ICommand value)
    {
        d.SetValue(CommandProperty, value);
    }

    public static ICommand GetCommand(DependencyObject d)
    {
        return (ICommand) d.GetValue(CommandProperty);
    }

    private static void OnCommandPropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        var listView = dependencyObject as ListViewBase;
        if (listView != null)
            listView.ItemClick += (sender, itemClickEventArgs) =>
            {
                var viewBase = sender as ListViewBase;
                var command = GetCommand(viewBase);

                if (command != null && command.CanExecute(itemClickEventArgs.ClickedItem))
                    command.Execute(itemClickEventArgs.ClickedItem);
            };
    }
}
 
The command in the ViewModel is set up like this:

public class SportsViewModel : ViewModelBase
 {
     public ObservableCollection<Sport> Sports { get; set; }
     public RelayCommand<Sport> SportSelected { get; private set; }

     public SportsViewModel()
     {
         SportSelected = new RelayCommand<Sport>(sport =>
         {
             if (sport == null) return; //should not happen
             _navigationService.NavigateTo(typeof(LeaguesView), sport.Id);
         });

     }

    //and so on...
}
 
And this is how I use this command in the XAML view:

<ListView IsItemClickEnabled="True" SelectionMode="None"
    commands:ItemClickCommand.Command="{Binding SportSelected}"
        ItemsSource="{Binding Sports}"  >
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}"  />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Remember to set the IsItemClickEnabled and SelectionMode properties for your ListView or nothing will happen when you click the items in the list Smile

No Comments