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 )

Google+ photo

You are commenting using your Google+ 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 )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Archives
Categories

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

Join 9 other followers

%d bloggers like this: