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. Download a free trial of UI for WPF
  4. George
    Admin
    George avatar
    1325 posts
    Member since:
    Dec 2014

    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 >>

  5. 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!

  6. 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;                                                                                                  
                                                                                                  }
                                                                                              });
               }
           }
       }

  7. 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).

  8. 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.

    ++

  9. 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);
            }
        }
    }

  10. 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.

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

    Posted 21 Feb 2013 Link to this post

    To delete

Back to Top
Download a free trial of UI for WPF