Click here to Skip to main content
11,639,554 members (64,818 online)
Click here to Skip to main content
Add your own
alternative version

Managing Multiple selection in View Model (.NET Metro Style Apps)

, 29 Jun 2012 CPOL 30.6K 1.9K 12
This article provides Attached Behavior based approach to manage Multiple Selection in Collection Based UI control from the View Model. All the code in this article is strictly applicable to Win 8 metro style apps. Though the Behaviors can be easily adapted to WPF/Silverlight.
Multiselect_in_VM.zip
Multiselect in VM
~$ltiselect Binding in ViewModel-Metro.docx
~$w Microsoft Word Document.docx
Ext
winrtbehaviors-14177.zip
winrtbehaviors-14177
Multiselect Binding in ViewModel-Metro.docx
MultiselectSample
depend
GalaSoft.MvvmLight.Win8.dll
WinRtBehaviors.dll
MultiselectSample
Assets
Logo.png
SmallLogo.png
SplashScreen.png
StoreLogo.png
bin
Debug
AppX
Assets
Logo.png
SmallLogo.png
SplashScreen.png
StoreLogo.png
Common
GalaSoft.MvvmLight.Win8.dll
microsoft.system.package.metadata
S-1-5-21-860198490-3370951563-2996008965-1001.pckgdep
MultiselectSample.exe
resources.pri
vs.appxrecipe
WinRtBehaviors.dll
WinRtExt.dll
Common
GalaSoft.MvvmLight.Win8.dll
MultiselectSample.build.appxrecipe
MultiselectSample.exe
resources.pri
WinRtBehaviors.dll
WinRtExt.dll
WinRtExt.pri
Common
MultiselectSample_TemporaryKey.pfx
obj
Debug
Common
intermediatexaml
TempPE
Package.appxmanifest
Properties
WinRtBehaviors
bin
Debug
WinRtBehaviors.dll
WinRtBehaviors.pri
obj
Debug
TempPE
Properties
WinRtBehaviors.csproj.vspscc
WinRtBehaviors.vssscc
WinRtExt
Behavior
bin
ARM
Debug
Release
Debug
WinRtBehaviors.dll
WinRtBehaviors.pri
WinRtExt.dll
WinRtExt.pri
Release
x64
Debug
Release
x86
Debug
Release
obj
Debug
TempPE
Properties
ori
namespace WinRtExt.Behavior
{
    #region usings
    using System.Collections.ObjectModel;
    using System.Collections.Specialized;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using WinRtBehaviors;
    #endregion

    /// <summary>
    /// Adds Multiple Selection behavior to ListViewBase
    /// This adds capabilities to set/get Multiple selection from Binding (ViewModel)
    /// </summary>
    public class MultiSelectBehavior : Behavior<ListViewBase>
    {
        #region SelectedItems Attached Property
        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(
            "SelectedItems",
            typeof(ObservableCollection<object>),
            typeof(MultiSelectBehavior),
            new PropertyMetadata(new ObservableCollection<object>(), PropertyChangedCallback));
        
        #endregion

        #region private
        private bool _selectionChangedInProgress; // Flag to avoid infinite loop if same viewmodel is shared by multiple controls
        #endregion

        public MultiSelectBehavior()
        {
            SelectedItems = new ObservableCollection<object>();
        }

        public ObservableCollection<object> SelectedItems
        {
            get { return (ObservableCollection<object>)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.SelectionChanged += OnSelectionChanged;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.SelectionChanged -= OnSelectionChanged;
        }

        private static void PropertyChangedCallback(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            NotifyCollectionChangedEventHandler handler =  (s, e) => SelectedItemsChanged(sender, e);
            if (args.OldValue is ObservableCollection<object>)
            {
                (args.OldValue as ObservableCollection<object>).CollectionChanged -= handler;
            }

            if (args.NewValue is ObservableCollection<object>)
            {
                (args.NewValue as ObservableCollection<object>).CollectionChanged += handler;
            }
        }

        private static void SelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (sender is MultiSelectBehavior)
            {
                var listViewBase = (sender as MultiSelectBehavior).AssociatedObject;

                var listSelectedItems = listViewBase.SelectedItems;
                if (e.OldItems != null)
                {
                    foreach (var item in e.OldItems)
                    {
                        if (listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Remove(item);
                        }
                    }
                }

                if (e.NewItems != null)
                {
                    foreach (var item in e.NewItems)
                    {
                        if (!listSelectedItems.Contains(item))
                        {
                            listSelectedItems.Add(item);
                        }
                    }
                }
            }
        }
        
        private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (_selectionChangedInProgress) return;
            _selectionChangedInProgress = true;
            foreach (var item in e.RemovedItems)
            {
                if (SelectedItems.Contains(item))
                {
                    SelectedItems.Remove(item);
                }
            }

            foreach (var item in e.AddedItems)
            {
                if (!SelectedItems.Contains(item))
                {
                    SelectedItems.Add(item);
                }
            }
            _selectionChangedInProgress = false;
        }
     }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Fun@learn
Software Developer (Senior)
India India
Software Engineer based out in Noida.

Technology skillset – .NET, WPF, WCF, LINQ, XAML.

Started blogging on http://1wpf.wordpress.com/


Stackoverflow Profile -> http://stackoverflow.com/users/649524/tilak

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150731.1 | Last Updated 29 Jun 2012
Article Copyright 2012 by Fun@learn
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid