Windows Phone Toolkit MultiselectList in depth| Part2: Data Binding

原文地址:http://windowsphonegeek.com/articles/Windows-Phone-Toolkit-MultiselectList-in-depth-Part2-Data-Binding

Windows Phone Toolkit MultiselectList in depth| Part2: Data Binding

published on: 11/3/2011   | Views: 7091   | Tags: WP7Toolkit
1
2
3
4
5

Rate Now!

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.

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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.

?
1
2
3
4
5
< phone:PhoneApplicationPage.Resources >
     < DataTemplate x:Key = "CustomItemTemplate" >
         < TextBlock Text = "{Binding Name}" />
     </ DataTemplate >
</ phone:PhoneApplicationPage.Resources >

Step2. Define a custom ItemInfoTemplate in the page Resources.

?
1
2
3
4
5
< 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:

?
1
2
3
< toolkit:MultiselectList Grid.Row = "1" x:Name = "multiSelectList"
          ItemTemplate = "{StaticResource CustomItemTemplate}"
          ItemInfoTemplate = "{StaticResource CustomItemInfoTemplate}" />

Step4Set the MultiselectList ItemsSource

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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:

?
1
2
3
4
5
6
7
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():

?
1
2
3
4
5
6
public MainPage()
{
     InitializeComponent();
     this .ShowNormalStateAppBar();
     //...
}

Step8. Subscribe to the MultiselectList IsSelectionEnabledChanged event and add the following code in its handler:

?
1
2
3
4
5
public MainPage()
{
     //...
     this .multiSelectList.IsSelectionEnabledChanged += new DependencyPropertyChangedEventHandler(multiSelectList_IsSelectionEnabledChanged);
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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();
     }
}

clip_image002NOTE: It is important to handle the IsSelectionEnabledChanged event since selection mode can be triggered by user interaction also, and not only by setting the IsSelectionEnabled property.

Step9. Add a helper method that sets the IsSelected property of MultiselectItems:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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:

?
1
2
3
4
5
6
7
8
9
10
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:

?
1
2
3
4
5
6
7
8
9
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:

?
1
2
3
4
5
6
7
8
9
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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
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:

clip_image004clip_image006clip_image008

clip_image010

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?

What if you have more than "30" Pizzas Topping???

posted by: G Cupertino on 6/3/2012 11:01:39 PM

Hi, it's a great post, but if you add more items to the list, let's say you have like 60 items and you click select all, only the first 20 items will be selected. Could it be memory performance? It doesn't work when the line is not visible. If the line is not visible, returns null. Any idea?

Add comment to 'Windows Phone Toolkit MultiselectList in depth| Part2: Data Binding'


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值