This is a migrated thread and some comments may be shown as answers.

Binding multi selected items in MVVM

6 Answers 2350 Views
DataGrid
This is a migrated thread and some comments may be shown as answers.
Maurice
Top achievements
Rank 1
Maurice asked on 24 Jan 2017, 10:32 AM

Hi,

I want to bind the selecteditems. It works when selectionMode = single. But I want to use Multiple rows with SelectionMode="Multiple"

I tried to use a ObservableCollection for SelectedItem but that did not work.

This works with single item.
<telerikGrid:RadDataGrid  ItemsSource="{Binding GridSource}" SelectedItem="{Binding SelectedItem}">

 

Any solution for this?

Thank you!

6 Answers, 1 is accepted

Sort by
0
Lance | Manager Technical Support
Telerik team
answered on 24 Jan 2017, 11:00 PM
Hello Maurice,

The reason you'renot able to bind to SelectedItems directly is because it is a read-only collection.

One option you can use to accomplish the same thing is take advantage of UWP's x:Bind to feature of binding to an event handler in the ViewModel.

<grid:RadDataGrid ItemsSource="{Binding GridItems}"
    SelectionChanged="{x:Bind ViewModel.RadDataGrid_OnSelectionChanged}"
    SelectionMode="Multiple"/>


This will let you maintain MVVM and still use the DataGrid's SelectionChanged args (e.AddedItems and e.RemovedItems) .

I've put together a small demo where you can make multiple selection in the DataGrid and you'll see those selections in a RadListView to the right. The ListView is bound to the ViewModel's "SelectedGridItems" property. As you select and deselect items, SelectedGridItems will be updated.

I've attached the demo and here's a screenshot at runtime:





Behavior Based Approach

Another approach you can take is to use XAML Behaviors. This will also sync the SelectedItems between the DataGrid and your ViewModel's SelectedGridItems in an MVVM friendly manner.

Here's the XAML for the DataGrid using a behavior:

<grid:RadDataGrid x:Name="DataGrid"
            ItemsSource="{Binding GridItems}"
            SelectionMode="Multiple">
    <interactivity:Interaction.Behaviors>
        <behaviors:MyMultiSelectBehavior SelectedItems="{x:Bind ViewModel.SelelectedGridItems}" />
    </interactivity:Interaction.Behaviors>
</grid:RadDataGrid>


And here's the MyMultiSelectBehavior behavior class (Important, you need to add the Microsoft.Xaml.Behaviors.Uwp.Managed Nuget package to the project):

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


Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Maurice
Top achievements
Rank 1
answered on 26 Jan 2017, 11:35 AM

Thank you for your answer.

I can't use x:bind because I have to target Build 10240.

Also in the example of xaml behavior x:bind is used.

I will start reading the documentation of xaml behavior if I can use this aproach.

 

Kind regards,

Maurice

0
Maurice
Top achievements
Rank 1
answered on 26 Jan 2017, 01:45 PM

Fixed it with:

<interactivity:Interaction.Behaviors>
  <core:EventTriggerBehavior EventName="SelectionChanged">
   <core:InvokeCommandAction Command="{Binding SelectionChangedCommand}"  />
  </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>

 

Kind regards,

Maurice

 

0
Accepted
Lance | Manager Technical Support
Telerik team
answered on 26 Jan 2017, 05:36 PM
Hello Maurice,

Yes, the EventToCommand approach works, just be aware that it doesn't pass the event args automatically. You can either create a custom behavior like Normal does in this post or use a converter with your InvokeCommandAction like Iris does here.

Once you have the args passed to the command, you'll be able to get e.AddedItems and e.RemovedItems to keep your VM's SelectedItems collection in sync.

Regards,
Lance | Tech Support Engineer, Sr.
Telerik by Progress
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Cody
Top achievements
Rank 1
answered on 06 Oct 2017, 11:22 PM

Woo lets bump a dinosaur thread... 

Anyways I have implemented the multi-select behavior solution without thinking things through all the way... Is it at all possible to programatically select multiple items on a telerik RadDataGrid?

0
Lance | Manager Technical Support
Telerik team
answered on 10 Oct 2017, 05:28 PM
Hello Cody,

You can add or remove items from the DataGrid's SelectedItems property to accomplish this.

Let's say I have a list of Students in the view model:

public class ViewModel
{
    public ViewModel()
    {
    }
 
    public ObservableCollection<Student> Students { get; set; } = new ObservableCollection<Student>();
}


that the DataGrid is bound to: 

<grid:RadDataGrid x:Name="MyDataGrid" ItemsSource="{Binding Students}" />


If I wanted to programmatically make the first item selected when the page loads, I would do this:

private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    var vm = DataContext as ViewModel;
    MyDataGrid.SelectedItems.Add(vm?.Students.FirstOrDefault());
}

Let me know if you have any further questions.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
Tags
DataGrid
Asked by
Maurice
Top achievements
Rank 1
Answers by
Lance | Manager Technical Support
Telerik team
Maurice
Top achievements
Rank 1
Cody
Top achievements
Rank 1
Share this question
or