Handling multi-select lists in WP8

In Windows Store apps, there is a control called a GridView, which supports multi-select. That is, you can click and select multiple items in the grid, these are your .SelectedItems. For example:

image

Well, in Windows Phone I wanted to accomplish something similar. But how do you do this? Well, it turns out the Microsoft.Phone.Controls.Toolkit has some pretty good controls! Add a reference like this:

image

In the toolkit, there is a LongListMultiSelector. This looks and acts very similar to the LongListSelector you know and love (hate, really) – but this allows multiple selections. One additional thing I wanted to do though, was to show/hide menu items based on what is selected. The end-result being something like below:

By default, with nothing selected, I have a Refresh and an Add menu item (or I can click on the item to go to the details page for that entry):

ss1

if I click just to the left of the list item, it shows the checkboxes. In this case, when exactly ONE item is selected, I want to allow the Refresh, Add, Edit, and Delete menu items:

ss2

and lastly, if more than one item is selected, I want to enable the Refresh, Add, and Delete only – because I don’t have a way to Edit more than one item:

ss3

So – how is this done? First, in XAML, I have a LongListMultiSelector defined like this (simplified):

<toolkit:LongListMultiSelector x:Name="legalEntityLongListSelector"
                                ItemsSource="{Binding LegalEntityItems}"
                                SelectionChanged="LongListSelector_SelectionChanged">
    <toolkit:LongListMultiSelector.ItemTemplate>
        <DataTemplate>
            <Border BorderThickness="1" BorderBrush="DarkGray" Background="White" 
                    CornerRadius="1" Width="Auto" x:Uid="{Binding LegalEntityId}">
                <StackPanel Margin="0,0,0,17">
                    <toolkit:ContextMenuService.ContextMenu>
                        <toolkit:ContextMenu >
                            <toolkit:MenuItem Header="Edit" Foreground="Black" Click="editMenuItem_Click"/>
                            <toolkit:MenuItem Header="Delete" Foreground="Black" Click="deleteMenuItem_Click"/>
                            <toolkit:MenuItem Header="Copy to Clipboard" Foreground="Black" Click="copyMenuItem_Click"/>
                            <toolkit:MenuItem Header="Send via E-mail..." Foreground="Black" Click="sendEmailMenuItem_Click"/>
                            <toolkit:MenuItem Header="Send via SMS..." Foreground="Black" Click="sendSmsMenuItem_Click"/>
                        </toolkit:ContextMenu>
                    </toolkit:ContextMenuService.ContextMenu>
                    <TextBlock Text="{Binding LegalEntityName}" Foreground="Black" TextWrapping="Wrap" 
                                Margin="12,0,12,0" Style="{StaticResource AppTextSubtitleStyle}" 
                                FontWeight="Bold"/>
                    <TextBlock Text="{Binding Description}" Foreground="Black" TextWrapping="Wrap" 
                                Margin="24,0,12,-12"/>
                </StackPanel>
            </Border>
        </DataTemplate>
    </toolkit:LongListMultiSelector.ItemTemplate>
</toolkit:LongListMultiSelector>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

then, in code, I wire up to the SelectionChanged event of the list, and show/hide buttons based on the state of the selection:

private void LongListSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (this.ApplicationBar.Buttons.Contains(editAppBarButton))
        this.ApplicationBar.Buttons.Remove(editAppBarButton);

    if (this.ApplicationBar.Buttons.Contains(deleteAppBarButton))
        this.ApplicationBar.Buttons.Remove(deleteAppBarButton);

    if (this.legalEntityLongListSelector.SelectedItems.Count == 0)
    {
        // Do nothing; already removed.
    }
    else if (this.legalEntityLongListSelector.SelectedItems.Count == 1)
    {
        this.ApplicationBar.Buttons.Add(editAppBarButton);
        this.ApplicationBar.Buttons.Add(deleteAppBarButton);
    }
    else if (this.legalEntityLongListSelector.SelectedItems.Count > 1)
    {
        this.ApplicationBar.Buttons.Add(deleteAppBarButton);
    

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

this is where the edit and delete buttons were already predefined and exist as class-level field variables:

private void InitializeExtraMenuButtons()
{
    editAppBarButton = new ApplicationBarIconButton()
    {
        Text = "Edit",
        IconUri = new Uri("/Assets/AppBar/edit.png", UriKind.Relative)
    };
    editAppBarButton.Click += editAppBarButton_Click;

    deleteAppBarButton = new ApplicationBarIconButton()
    {
        Text = "Delete",
        IconUri = new Uri("/Assets/AppBar/delete.png", UriKind.Relative)
    };
    deleteAppBarButton.Click += deleteAppBarButton_Click;
}

private ApplicationBarIconButton editAppBarButton = null;

private ApplicationBarIconButton deleteAppBarButton = null;

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

This gives a nice user experience. As I select and deselect items, the menu buttons add or remove automatically. I’m sure you could probably do this with MVVM too, and a custom converter, but that’d be a project for another day.

Posted in Uncategorized, WindowsPhone, XAML

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 5 other followers

%d bloggers like this: