Nico's digital footprint

I grew up in the nineties, that makes me awesome by default

LongListSelector with bindable SelectedItem

by Nico

In Windows Phone 8 Microsoft wants us to use the LongListSelector instead of the ListBox. But it seems they forgot about something, the SelectedItem property of the LongListSelector isn’t bindable. There are multiple work-arounds for this like event to command in XAML or setting the viewmodel property from the SelectionChanged event. That last one breaks your entire MVVM setup since the code behind of the view is now directly setting properties on the viewmodel.

Today I once again ran into this problem and decided to extend the LongListSelector to allow SelectedItem binding (note: I haven’t searched for an existing extended LongListSelector so it might as well exist somewhere else, this is just my attempt at it).

Create either a Windows Phone class library or a new class in a WP8 project, I called it ExtendedSelector and have it derive from LongListSelector, you’ll need to add a using statement for the Microsoft.Phone.Controls namespace.

Code Snippet
  1. public class ExtendedSelector : LongListSelector

First we’ll need a dependency property

Code Snippet
  1. public static readonly DependencyProperty SelectedItemProperty =
  2.     DependencyProperty.Register("SelectedItem", typeof (object), typeof (ExtendedSelector), new PropertyMetadata(default(object)));

and the property that is set through the DP

Code Snippet
  1. public new object SelectedItem
  2. {
  3.     get { return GetValue(SelectedItemProperty); }
  4.     set { SetValue(SelectedItemProperty, value); }
  5. }

Notice the “new” keyword on line 1? LongListSelector already has a SelectedItem property of type object, by using the new keyword we make the ExtendedSelector use our version of the property instead of the one from its base class

So now we have a property that can be bound to an object on our viewmodel, all there’s left to do now is set the actual selected item to the property. We do this by handling the SelectionChanged event, the event handler is hooked up in the constructor.

Code Snippet
  1. public ExtendedSelector()
  2. {
  3.     SelectionChanged += (sender, args) =>
  4.     {
  5.             SelectedItem = args.AddedItems[0];
  6.     };
  7. }

And that’s it, we now have a LongListSelector with a bindable SelectedItem property

Multi-select

Let’s take it a step further, we want to enable multi-selection of items in our ExtendedSelector.

Start by adding another dependency property

Code Snippet
  1. public static readonly DependencyProperty SelectionModeProperty =
  2.      DependencyProperty.Register("SelectionMode", typeof (SelectionMode), typeof (ExtendedSelector), new PropertyMetadata(default(SelectionMode)));
  3.  
  4. public SelectionMode SelectionMode
  5. {
  6.      get { return (SelectionMode) GetValue(SelectionModeProperty); }
  7.      set { SetValue(SelectionModeProperty, value); }
  8. }

SelectionMode is an enum containing three types of modes

  • Single
  • Multiple
  • Extended

I only need single and multiple, so I’m not going to do anything with Extended. Change the constructor of the ExtendedSelector to this

Code Snippet
  1. public ExtendedSelector()
  2. {
  3.     SelectionMode = SelectionMode.Single;
  4.  
  5.     SelectionChanged += (sender, args) =>
  6.     {
  7.         if(SelectionMode == SelectionMode.Single)
  8.             SelectedItem = args.AddedItems[0];
  9.         else if (SelectionMode == SelectionMode.Multiple)
  10.         {
  11.             if (SelectedItem == null)
  12.             {
  13.                 SelectedItem = new List<object>();
  14.             }
  15.  
  16.             foreach (var item in args.AddedItems)
  17.             {
  18.                 ((List<object>)SelectedItem).Add(item);                   
  19.             }
  20.  
  21.             foreach (var removedItem in args.RemovedItems)
  22.             {
  23.                 if (((List<object>) SelectedItem).Contains(removedItem))
  24.                 {
  25.                     ((List<object>) SelectedItem).Remove(removedItem);
  26.                 }
  27.             }
  28.         }
  29.     };
  30. }

When the class is instantiated we default the SelectionMode to Single, when the property is set from Xaml the setter fires after the constructor, so this is a safe place to put that. Next in the event handler we check for the SelectionMode, if it’s set to Single, nothing changes. When set to Multiple we check if SelectedItem already contains items, if it does add the newly selected item to the list, if it doesn’t we’ll instantiate SelectedItem first as a List<object>. If there are any deselected items we remove them from the list.

And that’s it. A problem easily solved. I’m just hoping that the product team will actually include this functionality in the next SDK update so this post becomes obsolete.

Conclusion

This post is a quick fix for the LongListSelector so it supports binding to SelectedItem. If you want the complete class, grab it on GitHub

Update

Scott Lovegrove pointed out that the Windows Phone toolkit (http://phone.codeplex.com/ ) has a LongListMultiSelector, allowing for multiple item selection. It still doesn't have a bindable SelectedItem property but it should be pretty easy to make one like I did with the normal LongListSelector it his post.


Tags:

.Net | WP8 | XAML

Don’t forget the system tray in your WP8 app

by Nico

The system tray in Windows Phone 8 is the small bar at the top where the clock, signal strength, connectivity icons, etc. reside. In most apps I’ve used developers tend to do one of two things there:

  • leave it
  • hide it

An example here is Microsoft’s Facebook app (yes, even the first party apps do this), take a look

This is a pretty decent looking app (yes it violates a bunch of “Modern UI” guidelines but it does look decent). However, the black system tray at the top of the screen breaks the experience. It feels like the app lies on top of the homescreen, while this is actually true it’s a better user experience to suck the user completely into the application.

Another option for the Facebook app would be to hide the system tray, this won’t break the experience for the user on the visual side.

But this solution has another downside, the Facebook app needs an active internet connection to work, suppose the app throws an error saying that your internet connection is down, what’s your first reaction? You check the signal strength and / or wifi connectivity icon, and where do those live? In the system tray that is hidden now, so the user needs to exit the app to check the system tray (same goes for checking the time).

Only hide the system tray when your app absolutely requires it, like a game that needs all the screen estate it can get.

So let’s try a third solution, something a lot of Windows Phone developers tend to forget or don’t know is possible, we can style the system tray. This is what the Facebook app could look like

By simply giving the system tray the same color as the header bar of the app we’ve give the app a little extra while still having a visible system tray.

I used this approach in my Traffic Chat app

Same story in this app, it looks much more like a part of the OS instead of “just an app”.

Let’s do it!

It’s actually very easy to get this done.

In your Windows Phone application, navigate to the App.xaml page. In that page there should be an Application.Resources tag. As you might (should) know, we can define application wide styles here, if we don’t provide a key to a style it applies to all controls of the specified type throughout the app. Sounds easy enough, let’s do it.

Code Snippet
  1. <Style TargetType="phone:PhoneApplicationPage">
  2.     <Setter Property="shell:SystemTray.BackgroundColor" Value="Red" />
  3.     <Setter Property="shell:SystemTray.ForegroundColor" Value="Green" />
  4. </Style>

The style has a target type of PhoneApplicationPage, the class that is used by all pages in a Windows Phone app. We set the backgroundcolor to Red and the Foregroundcolor to Green, this will look very pretty right? Glimlach

If we run the app now you’ll see that nothing has changed. A downside of this is that not providing a key doesn’t work for the PhoneApplicationPage, so we’ll need to name the style and apply it to every page in the application.

Change the above code to this (add a key, name it whatever you want)

Code Snippet
  1. <Style x:Key="DefaultPageStyle" TargetType="phone:PhoneApplicationPage">
  2.     <Setter Property="shell:SystemTray.BackgroundColor" Value="Red" />
  3.     <Setter Property="shell:SystemTray.ForegroundColor" Value="Green" />
  4. </Style>

And on every page that you want to style the systemtray, apply the style (line 15 in this code block).

Code Snippet
  1. <phone:PhoneApplicationPage
  2.     x:Class="PhoneApp1.MainPage"
  3.     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  4.     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  5.     xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
  6.     xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
  7.     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  8.     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  9.     mc:Ignorable="d"
  10.     FontFamily="{StaticResource PhoneFontFamilyNormal}"
  11.     FontSize="{StaticResource PhoneFontSizeNormal}"
  12.     Foreground="{StaticResource PhoneForegroundBrush}"
  13.     SupportedOrientations="Portrait" Orientation="Portrait"
  14.     shell:SystemTray.IsVisible="True"
  15.     Style="{StaticResource DefaultPageStyle}">

If we run the app now we’ll get a “beautiful” styled system tray.

 

Conclusion

Styling the system tray is something that is often overlooked. Spend some time on this, it’ll make your app look even better without annoying your users with a hidden system tray. It’s easy to do and doesn’t take a lot of time.

Download the Green/Red system tray app from my SkyDrive


Tags:

.Net | Devices | WP7 | WP8 | XAML

  Log in

About the author

Hi,

My name is Nico, I’m an MVP Windows Platform Development living in Belgium.
I’m currently employed as a .NET consultant at RealDolmen, one of Belgium’s leading IT single source providers.

I'm also founding member and board member of the Belgian Metro App Developer Network, a user group focussed on Windows 8 and Windows Phone development. If you're in Belgium feel free to drop by if we're doing an event. http://www.madn.be

Since June 2012 I'm a proud member of Microsoft's Extended Experts Team Belgium. And in February 2013 I became a member of DZone's Most Valuable Bloggers family.

In 2013 I became a book author and wrote "Windows 8 app projects, XAML & C# edition".

In 2014 I received the MVP award for the very first time.

I hope to get feedback from my readers either through comments, mail (nico_vermeir@hotmail.com), twitter, facebook, …

 

mvp

 

mvp

 

 

MeetLogo

 

MVBLogo

mybook

 

Month List