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