Visually Located

XAML and GIS

Making the Windows Phone Toolkit ListPicker ItemsPanel display a WrapPanel

There are many things that should be part of the Windows Phone SDK and the ListPicker is one of them. There are so many aspects of the phone that use a control that the ListPicker was based on. One of these is the accent color picker. In Phone 7 the phone would display a vertical list of colors with the name of the colors next to it. In Phone 8 they changed this experience and went with a WrapPanel.

AccentColors

If you want to to get this same experience, you’ll want to use the ListPicker from the Windows Phone Toolkit. The ListPicker will first display what appears to be a ComboBox, yet when you tap this ‘ComboBox’ it opens up and takes over the entire phone. This is all pretty standard and the ListPicker covers this perfectly. Where it fails us is when we want to change how the ListPicker stacks it’s items. This is generally done by changing the ItemsPanel of an ItemsControl. Unfortunately the ListPicker does not allow you to change the ItemsPanel. If you download or browse the source for the ListPicker, you’ll see that it uses a PhoneApplicationPage that has a ListBox in it. The code behind of this page set the ItemTemplate based on a property from the ListPicker, but this is the only one it sets based on a property of the ListPicker.

So here we are with a great control from the toolkit. It allows us to do pretty much everything we need to, but it does not allow us to display a color picker like the native accent color picker. There are two ways that we can accomplish this. The first is to download the source and change it to allow for the ability to override the ItemsPanel. Downloading and changing source is usually risky. It’s risky because you then loose out on any updates that the maintainers may push out. It’s ok provided that you’re ok merging updates with your source.

The second it much easier, does not require you to download source or change any of the toolkit. This simple change requires you to create an implicit style for the ListBox control. Implicit styles allow you to specify a style that all controls of that type will use. To accomplish this, place the following style within your app.xaml

<Style TargetType="ListBox">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <toolkit:WrapPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

With this in your app.xaml, you can display a WrapPanel within the ListPicker. Unfortunately, with this style, all ListBoxes will display a WrapPanel. If you have other ListBoxes within your app, they will display WrapPanels. You can get the other ListBoxes to display as normal by adding the following style to your app.xaml.

<Style x:Key="StandardListBoxStyle" TargetType="ListBox">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListBox">
                <ScrollViewer x:Name="ScrollViewer" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Foreground="{TemplateBinding Foreground}" Padding="{TemplateBinding Padding}">
                    <ItemsPresenter/>
                </ScrollViewer>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


Now use this style within your app.

<ListBox Style="{StaticResource StandardListBoxStyle}" ItemsSource="{Binding MyItems}"/>

If you use this approach and you have another ListPicker that you want to use in FullMode, it will display a WrapPanel. If you don’t want to always display a WrapPanel within your ListPicker, or if you don’t want to set the style manually then you’ll need to modify the source code of the ListPicker.

To begin you’ll need to download the source for the Windows Phone Toolkit. The toolkit comes with four projects, two under a Windows Phone 7 folder and two under a Windows Phone 8 folder. The projects use the same code for most of the files. These files have a central location and are added as a link.  You’ll need to modify one file that is shared and another file within each phone 7 and phone 8 project. Open the ListPickerPage.xamlcs file from both the phone 7 and phone 8 project. The ListPicker already has a FullModeItemTemplate, we can continue this style by adding a FullModeItemsPanel.

/// <summary>
/// Gets or sets the ItemsPanel.
/// </summary>
public ItemsPanelTemplate FullModeItemsPanel { get; set; }

Within the OnNavigatedTo method, add the following

if (FullModeItemsPanel != null)
{
    Picker.ItemsPanel = FullModeItemsPanel;
}

Now open the LickPicker.cs file from one of the toolkit projects (not a samples project). Add the following dependency property.

/// <summary>
/// Gets or sets the ItemsPanel used to display the items when ListPickerMode is set to Full.
/// </summary>
public ItemsPanelTemplate FullModeItemsPanel
{
    get { return (ItemsPanelTemplate)GetValue(FullModeItemsPanelProperty); }
    set { SetValue(FullModeItemsPanelProperty, value); }
}
 
/// <summary>
/// Identifies the FullModeItemsPanel DependencyProperty.
/// </summary>
public static readonly DependencyProperty FullModeItemsPanelProperty =
    DependencyProperty.Register(
    "FullModeItemsPanel", 
    typeof(ItemsPanelTemplate), 
    typeof(ListPicker), 
    new PropertyMetadata(null));

Within the OnFrameNavigatedTo method you’ll want to add the following line.

_listPickerPage.FullModeItemsPanel = FullModeItemsPanel;

It’s best to add this line under where the FullModeItemTemplate is set for the page.

I said earlier that changing the source can be risky because you loose out on updates that come from the maintainers of the source. Unfortunately there is little effort going into any of the toolkits from Microsoft and we have yet to see a toolkit for Windows Store apps. Not only does no one work on these toolkit, but you cannot provide contributions. Pedro Lamas has taken the source from codeplex and put it up on github. Pedro is providing fixes and taking pull requests for this repro. I’ve already provided this change and you can download it and start going.