Windows Phone Toolkit MultiselectList in depth| Part2: Data Binding
published on: 11/3/2011 | Views: N/A | Tags: WP7Toolkit
by WindowsPhoneGeek
This is the second article about the new MultiselectList control from the latest release of the Windows Phone Toolkit - August 2011 (7.1 SDK). This time I am going to talk about data binding and using MultiselectList in more complex scenarios.
NOTE: In Part1 we talked about key properties, methods, events and the main features of the Windows Phone MultiselectList control. You can take a look at it for reference.
- Windows Phone Toolkit MultiselectList in depth| Part1: key concepts and API
- Windows Phone Toolkit MultiselectList in depth| Part2: Data Binding
Data Binding MultiselectList Step by Step
This example demonstrates how to populate the MultiselectList control with data using data binding. In this example the MultiselectList control is used to enable the user to select multiple ingredients from a list in order to create a custom pizza.
- Defining the Data Source
Here are the steps we will follow in order to create a data source:
Step1. Define the business/data class:
The first step is to define the data class. Let's create a "PizzaOption" class which exposes the following properties:
public class PizzaOption
{
public PizzaOption(string name)
{
this.Name = name;
}
public string Name
{
get;
set;
}
public string Note
{
get;
set;
}
public bool IsSelected
{
get;
set;
}
}
Step2. Create a sample collection with items of type TileItem:
public MainPage()
{
//...
List<PizzaOption> pizzaOptions = new List<PizzaOption>()
{
new PizzaOption("Olives"),
new PizzaOption("Mozzarella") { Note = "NEW"},
new PizzaOption("Mushrooms"),
new PizzaOption("Ham"),
new PizzaOption("Bacon"),
new PizzaOption("Pepperoni"),
new PizzaOption("Salami") { Note = "SOON"},
new PizzaOption("Tomatoes"),
new PizzaOption("Onions")
};
//...
}
- Data binding the MultiselectList
Step1. Define a custom ItemTemplate in the page Resources.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="CustomItemTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
Step2. Define a custom ItemInfoTemplate in the page Resources.
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="CustomItemInfoTemplate">
<TextBlock Text="{Binding Note}" />
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
Step3. Define a MultiselectList in XAML and set its ItemTemplate and ItemInfoTemplate:
<toolkit:MultiselectList Grid.Row="1" x:Name="multiSelectList"
ItemTemplate="{StaticResource CustomItemTemplate}"
ItemInfoTemplate="{StaticResource CustomItemInfoTemplate}"/>
Step4. Set the MultiselectList ItemsSource
ICollectionView pizzaOptionsCollectionView;
public MainPage()
{
//...
CollectionViewSource pizzaOptionSource = new CollectionViewSource();
pizzaOptionSource.Source = pizzaOptions;
this.pizzaOptionsCollectionView = pizzaOptionSource.View;
using (this.pizzaOptionsCollectionView.DeferRefresh())
{
this.pizzaOptionsCollectionView.SortDescriptions.Add(new SortDescription("IsSelected", ListSortDirection.Descending));
this.pizzaOptionsCollectionView.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Descending));
}
this.multiSelectList.ItemsSource = this.pizzaOptionsCollectionView;
}
The CollectionViewSource in the code above is used to sort the list by the values of the IsSelected and Name properties.
Step5. Add the following ApplicationButtons in code behind:
private ApplicationBarIconButton selectButton;
private ApplicationBarIconButton acceptButton;
private ApplicationBarIconButton cancelButton;
private ApplicationBarMenuItem selectAllMenuItem;
private ApplicationBarMenuItem unselectAllMenuItem;
// .
public MainPage()
{
InitializeComponent();
this.selectButton = new ApplicationBarIconButton();
this.selectButton.IconUri = new Uri("/Toolkit.Content/ApplicationBar.Select.png", UriKind.RelativeOrAbsolute);
this.selectButton.Text = "select";
this.selectButton.Click +=new EventHandler(selectButton_Click);
this.acceptButton = new ApplicationBarIconButton();
this.acceptButton.IconUri = new Uri("/Toolkit.Content/ApplicationBar.Check.png", UriKind.RelativeOrAbsolute);
this.acceptButton.Text = "accept";
this.acceptButton.Click +=new EventHandler(acceptButton_Click);
this.cancelButton = new ApplicationBarIconButton();
this.cancelButton.IconUri = new Uri("/Toolkit.Content/ApplicationBar.Cancel.png", UriKind.RelativeOrAbsolute);
this.cancelButton.Text = "cancel";
this.cancelButton.Click += new EventHandler(cancelButton_Click);
this.selectAllMenuItem = new ApplicationBarMenuItem();
this.selectAllMenuItem.Text = "select all";
this.selectAllMenuItem.Click += new EventHandler(selectAllMenuItem_Click);
this.unselectAllMenuItem = new ApplicationBarMenuItem();
this.unselectAllMenuItem.Text = "unselect all";
this.unselectAllMenuItem.Click += new EventHandler(unselectAllMenuItem_Click);
}
Step6. Create a new method that will configure the application bar for the normal state:
private void ShowNormalStateAppBar()
{
this.ApplicationBar.Buttons.Clear();
this.ApplicationBar.MenuItems.Clear();
this.ApplicationBar.Buttons.Add(this.selectButton);
this.pizzaOptionsCollectionView.Filter = this.IsSelectedFilter;
}
Step7. Call "ShowNormalStateAppBar" in the constructor of MainPage after InitializeComponent():
public MainPage()
{
InitializeComponent();
this.ShowNormalStateAppBar();
//...
}
Step8. Subscribe to the MultiselectList IsSelectionEnabledChanged event and add the following code in its handler:
public MainPage()
{
//...
this.multiSelectList.IsSelectionEnabledChanged += new DependencyPropertyChangedEventHandler(multiSelectList_IsSelectionEnabledChanged);
}
void multiSelectList_IsSelectionEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.multiSelectList.IsSelectionEnabled)
{
if (this.updateSelectedState)
{
IEnumerable<PizzaOption> pizzaOptions = this.pizzaOptionsCollectionView.SourceCollection as IEnumerable<PizzaOption>;
this.SetOptionsSelected(pizzaOptions, true, (pizzaOption) => pizzaOption.IsSelected);
}
this.ShowSelectionStateAppBar();
}
else
{
this.ShowNormalStateAppBar();
}
}
|
|
Step9. Add a helper method that sets the IsSelected property of MultiselectItems:
private void SetOptionsSelected(IEnumerable<PizzaOption> pizzaOptions, bool selected, Predicate<PizzaOption> predicate)
{
if (pizzaOptions == null)
{
return;
}
if (predicate == null)
{
predicate = (pizzaOption) => true;
}
ItemContainerGenerator itemContainerGenerator = this.multiSelectList.ItemContainerGenerator;
foreach (PizzaOption pizzaOption in pizzaOptions)
{
if (pizzaOption != null && predicate(pizzaOption))
{
DependencyObject visualItem = itemContainerGenerator.ContainerFromItem(pizzaOption);
MultiselectItem multiselectItem = visualItem as MultiselectItem;
if (multiselectItem != null)
{
// NOTE: this will also add an item to the SelectedItems collection
multiselectItem.IsSelected = selected;
}
}
}
}
Step10. Create a method that will configure the application bar for the selection state:
private void ShowSelectionStateAppBar()
{
this.ApplicationBar.Buttons.Clear();
this.ApplicationBar.MenuItems.Clear();
this.ApplicationBar.Buttons.Add(this.acceptButton);
this.ApplicationBar.Buttons.Add(this.cancelButton);
this.ApplicationBar.MenuItems.Add(this.selectAllMenuItem);
this.ApplicationBar.MenuItems.Add(this.unselectAllMenuItem);
this.pizzaOptionsCollectionView.Filter = null;
}
Step11. Create a method that is used to filter the collection in the normal state so that only selected items are displayed:
private bool IsSelectedFilter(object item)
{
PizzaOption pizzaOption = item as PizzaOption;
if (pizzaOption != null)
{
return pizzaOption.IsSelected;
}
return false;
}
Step12. Override OnBackKeyPress and add the following code:
protected override void OnBackKeyPress(CancelEventArgs e)
{
base.OnBackKeyPress(e);
if (this.multiSelectList.IsSelectionEnabled)
{
this.multiSelectList.IsSelectionEnabled = false;
e.Cancel = true;
}
}
Step13. Add the following code in the application buttons event handlers, defined in Step5:
void cancelButton_Click(object sender, EventArgs e)
{
this.multiSelectList.IsSelectionEnabled = false;
}
void acceptButton_Click(object sender, EventArgs e)
{
IEnumerable<PizzaOption> pizzaOptions = this.pizzaOptionsCollectionView.SourceCollection as IEnumerable<PizzaOption>;
foreach (PizzaOption pizzaOption in pizzaOptions)
{
pizzaOption.IsSelected = false;
}
foreach (object item in this.multiSelectList.SelectedItems)
{
PizzaOption pizzaOption = item as PizzaOption;
if (pizzaOption != null)
{
pizzaOption.IsSelected = true;
}
}
this.multiSelectList.IsSelectionEnabled = false;
}
void selectButton_Click(object sender, EventArgs e)
{
this.multiSelectList.IsSelectionEnabled = true;
}
private bool updateSelectedState = true;
void unselectAllMenuItem_Click(object sender, EventArgs e)
{
IEnumerable<PizzaOption> pizzaOptions = this.pizzaOptionsCollectionView.SourceCollection as IEnumerable<PizzaOption>;
this.SetOptionsSelected(pizzaOptions, false, null);
// IMPORTANT NOTE:
// when all items are unselected the selection mode automatically turns off
// is this a bug???
this.updateSelectedState = false;
this.multiSelectList.IsSelectionEnabled = true;
this.updateSelectedState = true;
}
void selectAllMenuItem_Click(object sender, EventArgs e)
{
IEnumerable<PizzaOption> pizzaOptions = this.pizzaOptionsCollectionView.SourceCollection as IEnumerable<PizzaOption>;
this.SetOptionsSelected(pizzaOptions, true, null);
}
Here is how the final result should look like:
That was all about data binding MultiselectList from the Windows Phone Toolkit - August 2011 (7.1 SDK) in depth.
Here is the full source code:
I hope that the post was helpful.
You can also follow us on Twitter @winphonegeek
Comments
posted by: LS on 3/31/2012 6:28:55 AM
How about a listbox with data binded content from an external source?
Our Top Articles & Free books
- Our FREE e-book: "Windows Phone Toolkit In Depth" 2nd edition
- 400+ Windows Phone Development articles in our Article Index
- 21 WP7 Toolkit in Depth articles covering all controls
- 12 WP7 Coding4Fun Toolkit in Depth articles covering all controls
- Performance Tips when creating WP7 apps
- Creating a WP7 Custom Control in 7 Steps
- WP7 working with VisualStates: How to make a ToggleSwitch from CheckBox
- What makes a WP7 App successful
- Creating theme friendly UI in WP7 using OpacityMask
- Implementing Windows Phone 7 DataTemplateSelector and CustomDataTemplateSelector
- All about Splash Screens in WP7 – Creating animated Splash Screen
- Getting Started with Unit Testing in Silverlight for WP7
- WP7 WatermarkedTextBox custom control
Our Top Tips & Samples
- All about WP7 Isolated Storage series
- WP7 Dynamically Generating DataTemplate in code
- 5 tips for a successful WP7 Marketplace submission
- WP7: Navigating to a page in different assembly
- WP7 ContextMenu: answers to popular questions
- WP7 ListBox: answers to popular questions
- WP7 working with Images: Content vs Resource build action
- WP7 Element Binding samples
- WP7 working with XML: reading, filtering and databinding
- Drawing in WP7: #2 Drawing shapes with finger
- WP7 TextBox Light theme problems - the solution
- Changing the WP7 Panorama Background Image dynamically with Animation
