RadListBox SelectedItems MVVM

10 posts, 0 answers
  1. Chris
    Chris avatar
    18 posts
    Member since:
    Nov 2003

    Posted 20 Feb 2012 Link to this post

    I can bind a ListBox ItemsSource to an ObservableCollection<T> and it works well.  But I need to allow the user to select n number of items in the list.  The list box supports this with SelectionMode="Multiple".  I figured if I bound the SelectedItem to a ObservableCollection<T> I'd be able to use it back in my ViewModel, but this is not working.  How do I bind the selected items from the ListBox to my ViewModel and have access to the selected items in the VM?

    Thanks,
    Chris

  2. AGM
    AGM avatar
    2 posts
    Member since:
    Feb 2012

    Posted 21 Feb 2012 Link to this post

    Exactly, what i want to know!

  3. George
    Admin
    George avatar
    1332 posts

    Posted 23 Feb 2012 Link to this post

    Hello,

     

    Currently the RadListBox control doesn't provide any way to manipulate the selected items in a MVVM friendly scenario. What I could suggest is to use the SelectionChanged property and in the handler you can get the RadListBox.SelectedItems property (it has only a getter and no setter). We consider this as a feature request and we logged it in our backlog system. You could vote for it and observe its progress here -
    http://www.telerik.com/support/pits.aspx#/public/silverlight/9902 
     

    All the best,
    George
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>

  4. Chris
    Chris avatar
    18 posts
    Member since:
    Nov 2003

    Posted 23 Feb 2012 Link to this post

    I do have a similar work around, I was just hoping the control had the feature and I was missing it.  That I did was attached a trigger, and using MVVMLight's EventToCommand mapped that to my ViewModel.  in the ViewModel I assign the selected items to a collection...

    My trigger (on the listbox):

    <i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged">
    <mvvm:EventToCommand Command="{Binding MethodChangedCommand}" CommandParameter="{Binding SelectedItems, ElementName=callMethodListBox}" />
    </i:EventTrigger>
    </i:Interaction.Triggers>

    Then in my ViewModel:
    MethodChangedCommand = new RelayCommand<IList>(
    items =>
    {
    _selectedCallMethods.Clear();
    foreach (var item in items)
    _selectedCallMethods.Add(item as NameValueViewModel<int>);
    });


    I'm still pretty new to MVVM, and there is probably a more elegant way to accomplish this, if others have a better way please feel free to share!

  5. AvgurD
    AvgurD avatar
    18 posts
    Member since:
    Oct 2012

    Posted 02 May 2012 Link to this post

    Hello!

    I found one solution for myself - but it's not "pure" MVVM.

    In VM:

    public Action OnSelectFirstDocumentType;
     
    private void LoadDocumentTypesComleted(LoadOperation<DocumentType> obj)
    {
        ...
        ...load content of listbox
        ...
        if (DocumentTypes.Count > 0)
        {
            OnSelectFirstDocumentType();
        }
    }
    In View:
    public partial class AddEditDocumentView
       {
           public AddEditDocumentView()
           {
               InitializeComponent();
               this.Loaded += new System.Windows.RoutedEventHandler(AddEditDocumentView_Loaded);
           }
     
           void AddEditDocumentView_Loaded(object sender, System.Windows.RoutedEventArgs e)
           {
               //handler - select first item in type's listbox
               if (this.DataContext as AddEditDocumentViewModel != null)
               {
                   (this.DataContext as AddEditDocumentViewModel).OnSelectFirstDocumentType = (() => if (DocTypeListBox.Items.Count > 0)
                                                                                                  {
                                                                                                       DocTypeListBox.SelectedIndex = 0;                                                                                                  
                                                                                                  }
                                                                                              });
               }
           }
       }

  6. AvgurD
    AvgurD avatar
    18 posts
    Member since:
    Oct 2012

    Posted 02 May 2012 Link to this post

    If you want to select custom item - you must create event like this

    public Action<int> OnSelectFirstDocumentType; 
    or 
    public Action<object> OnSelectFirstDocumentType; 

    and send index or item to select (and select it in handler in view).

  7. lnu
    lnu avatar
    19 posts
    Member since:
    Aug 2012

    Posted 01 Jun 2012 Link to this post

    Hi,

    I'm using an attached property for this scenario:

    using System.Collections;
    using System.Windows;
    using Telerik.Windows.Controls;
     
    namespace test
    {
        /// <summary>
        /// This class allow to bind selected Items from ListBox.
        /// </summary>
        public static class SelectedItemsHelperRadListBox
        {
            /// <summary>
            /// SelectedItems Attached Dependency Property.
            /// </summary>
            public static readonly DependencyProperty SelectedItemsProperty =
                DependencyProperty.RegisterAttached("MySelectedItems", typeof(IList), typeof(SelectedItemsHelperRadListBox), new FrameworkPropertyMetadata((IList)null, new PropertyChangedCallback(OnSelectedItemsChanged)));
     
            /// <summary>
            /// Gets my selected items.
            /// </summary>
            /// <param name="d">The d.</param>
            /// <returns></returns>
            public static IList GetMySelectedItems(DependencyObject d)
            {
                return (IList)d.GetValue(SelectedItemsProperty);
            }
     
            /// <summary>
            /// Sets my selected items.
            /// </summary>
            /// <param name="d">The d.</param>
            /// <param name="value">The value.</param>
            public static void SetMySelectedItems(DependencyObject d, IList value)
            {
                d.SetValue(SelectedItemsProperty, value);
            }
     
            /// <summary>
            /// Called when [selected items changed].
            /// </summary>
            /// <param name="sender">The sender.</param>
            /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
            private static void OnSelectedItemsChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                var listBox = sender as RadListBox;
                if (listBox != null)
                {
                    ReSetSelectedItems(listBox);
                    listBox.SelectionChanged += delegate
                    {
                        ReSetSelectedItems(listBox);
                    };
                }
            }
     
            /// <summary>
            /// Res the set selected items.
            /// </summary>
            /// <param name="listBox">The list box.</param>
            private static void ReSetSelectedItems(RadListBox listBox)
            {
                IList selectedItems = GetMySelectedItems(listBox);
                if (selectedItems != null)
                {
                    selectedItems.Clear();
                    if (listBox.SelectedItems != null)
                    {
                        foreach (var item in listBox.SelectedItems)
                        {
                            selectedItems.Add(item);
                        }
                    }
                }
            }
        }

    <telerik:RadListBox x:Name="xxx"
                                            Grid.Row="1"
                                            Helper:SelectedItemsHelperRadListBox.MySelectedItems="{Binding SelectedDatas}"
                                            ItemsSource="{Binding Datas}"
                                            SelectionMode="Extended"
                                            Margin="0,5,0,0">
    </<telerik:RadListBox>

    It does the job for me.

    ++

  8. Erik
    Erik avatar
    36 posts
    Member since:
    Jun 2012

    Posted 18 Aug 2012 Link to this post

    I modified the solution described here:
    http://blogs.telerik.com/vladimirenchev/posts/10-05-31/how-to-synchronize-your-ui-selected-items-with-your-data-context-using-mvvm-and-blend-behaviors-for-silverlight-and-wpf.aspx
    to work with the RadListBox:

    public class RadListBoxSelectedItemsBehavior : Behavior<RadListBox>
    {
        private RadListBox ListBox
        {
            get
            {
                return AssociatedObject;
            }
        }
     
        public INotifyCollectionChanged SelectedItems
        {
            get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }
     
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(RadListBoxSelectedItemsBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
     
     
        private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
        {
            var collection = args.NewValue as INotifyCollectionChanged;
            if (collection != null)
            {
                collection.CollectionChanged += ((RadListBoxSelectedItemsBehavior)target).ContextSelectedItemsCollectionChanged;
            }
        }
     
        protected override void OnAttached()
        {
            base.OnAttached();
     
            ListBox.SelectionChanged += ListBoxOnSelectionChanged;
        }
     
        private void ContextSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            UnsubscribeFromEvents();
     
            Transfer(SelectedItems as IList, ListBox.SelectedItems);
     
            SubscribeToEvents();
        }
     
        private void ListBoxOnSelectionChanged(object sender, SelectionChangedEventArgs selectionChangedEventArgs)
        {
            UnsubscribeFromEvents();
     
            Transfer(ListBox.SelectedItems, SelectedItems as IList);
     
            SubscribeToEvents();
        }
     
        private void SubscribeToEvents()
        {
            ListBox.SelectionChanged += ListBoxOnSelectionChanged;
     
            if (SelectedItems != null)
            {
                SelectedItems.CollectionChanged += ContextSelectedItemsCollectionChanged;
            }
        }
     
        private void UnsubscribeFromEvents()
        {
            ListBox.SelectionChanged -= ListBoxOnSelectionChanged;
     
            if (SelectedItems != null)
            {
                SelectedItems.CollectionChanged -= ContextSelectedItemsCollectionChanged;
            }
        }
     
        public static void Transfer(IList source, IList target)
        {
            if (source == null || target == null)
                return;
     
            target.Clear();
     
            foreach (var o in source)
            {
                target.Add(o);
            }
        }
    }

  9. Alfons
    Alfons avatar
    14 posts
    Member since:
    Mar 2012

    Posted 31 Jan 2013 Link to this post

    All the mentioned solutions above didn't fit my needs (I think): I had to be able to set the SelectedItems as well.

    I have a collection in an object and I want to edit my object in a RadDataForm.

    This is how I solved it:
    1. I added two DependencyProperties to my class derived from DataFormDataField: Population (all selectable items) and SelectedItems (which was bound to THE collection).
    2. Since the items of a RadListBox cannot be selected programmatically (correct me if I'm wrong), I created an ItemTemplate with a checkbox.
    3. The ListBox.ItemsSource I bound to my Population (via a MultiValueConverter).
    4. In this converter I combined both the DependencyProperties and created a List of objects with a Selected property (which was bound to the IsChecked property of the checkbox).
    5. To the checkbox I added two handlers for the Checked and Unchecked event. In here I added and removed items to and from the SelectedItems property.

    That's it. I hope this is useful to someone.

  10. Adrian
    Adrian avatar
    1 posts
    Member since:
    Feb 2013

    Posted 21 Feb 2013 Link to this post

    To delete

Back to Top