WPF – Binding ListBox SelectedItems – Attached Property VS Style

2 בMay 2014

6 comments

It seems List Box doesn’t support SelectedItems property Binding. Well since my application does support multiple items selection, I went looking for a solution. What I found was the following:

Support Multiple Selection Using Style

Add the following style in the listbox’s XAML:

  1. <ListBox.ItemContainerStyle>
  2.                               <Style TargetType=”{x:Type ListBoxItem}>
  3.                                   <Setter Property=“IsSelected” Value=”{Binding Mode=TwoWay, Path=IsSelected}/>
  4.                               </Style>
  5.                           </ListBox.ItemContainerStyle>

Add support for the styling in the view model:

We have to support the style by wrapping the original AnimalType class.

  1. publicclassAnimalTypeForView
  2.       {
  3.           publicbool IsSelected { get; set; }
  4.           publicAnimalType Type { get; set; }
  5.       }
  6.       publicList<AnimalType> AnimalTypes
  7.       {
  8.           get { return AnimalTypes; }
  9.           set
  10.           {
  11.               _AnimalTypes =value;
  12.               NotifyOfPropertyChange(() => _AnimalTypes);
  13.           }
  14.       }

I don’t like that, since it adds noise and mess to the view model code and it enforce us to use a single list (item source), which we have to look in to get the selected items list. It works, but It’s not perfect.

I decided to take a different approach, by using WPF’s Attached Properties.

Support Multiple Selection Using An Attach Property

The idea was to listen to list box’s selection changed event, grab the current single selected item and to add it to the view model’s list.

Define the attached property’s properties:

  1. publicstaticreadonlyDependencyProperty SelectedItemsProperty =
  2.         DependencyProperty.RegisterAttached(“SelectedItems”, typeof(IList),
  3.         typeof(ListBoxMultipleSelection),
  4.         newFrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
  5.         newPropertyChangedCallback(OnSelectedItemsChanged)));

Register the list box’s selected item change event when the collection is initiated :

  1. privatestaticvoid OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  2.         {
  3.             if (!_isRegisteredSelectionChanged)
  4.             {
  5.                 var listBox = (ListBox)d;
  6.                 list = listBox;
  7.                 listBox.SelectionChanged += listBox_SelectionChanged;
  8.                 _isRegisteredSelectionChanged =true;
  9.             }
  10.         }

Update the VM whenever the listbox’s  selected item changes:

  1. privatestaticvoid listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2.         {
  3.             //Get list box’s selected items.
  4.             IEnumerable listBoxSelectedItems = list.SelectedItems;
  5.             //Get list from model
  6.             IList ModelSelectedItems = GetSelectedItems(list);
  7.             //Update the model
  8.             ModelSelectedItems.Clear();
  9.             if (list.SelectedItems !=null)
  10.             {
  11.                 foreach (var item in list.SelectedItems)
  12.                     ModelSelectedItems.Add(item);
  13.             }
  14.             SetSelectedItems(list, ModelSelectedItems);
  15.         }

Update the view:

  1. <ListBox SelectionMode=“Multiple” local:ListBoxMultipleSelection.SelectedItems=”{Binding SelectedItems}

Update the view model:

  1. publicList<AnimalType> SelectedAnimalTypes

By using the attached property approach, both the view and the view model are clearer and cleaner.  The attached property is reusable and the hard work could use us again in the future.

Entire code can be found here.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

6 comments

  1. renu9 בOctober 2014 ב 3:52 pm

    Please post the code link. the above link does not work

    Reply
    1. Michael Loewenstein
      Michael Loewenstein16 בMay 2016 ב 9:45 am

      Please try again

      Reply
  2. GMF13 בJuly 2015 ב 2:54 am

    Your first solution is awesome!!!
    By Far – much better than the second solution offered.
    Thank you.

    Reply
  3. hrvoje9 בFebruary 2016 ב 1:21 pm

    Thank you for this solution.

    Reply
  4. cad2 בJune 2016 ב 11:53 pm

    the code link returns 404. Could you update the link, please?

    Reply