I am using a Telerik RadGridView in my application and it has a GridViewSelectColumn item in it, which allows me to select various items in the grid. I have a button that operates on this selection, but am not sure how to get the list of selected items. The problem is that I am using an MVVM pattern with Caliburn.Micro. Do I need to find the control in the view and traverse the list of selected items? That seems like a lot of work for a simple task. I would appreciate any ideas.
Asked
Active
Viewed 1.2k times
5 Answers
11
The problem with Telerik's RadGridView is, that its SelectedItem collection is read-only, so you cannot bind two-way to SelectedItems.
A workaround for this is to use a custom Behavior to do the synchronization between RadGridView and your ViewModels SelectedItem collection
You may use this Behavior:
// Behavior for synchronizing a RadDataGrid's SelectedItems collection with a SelectedItems collection of the ViewModel (the Network)
// The problem is, that RadDataGrid.SelectedItems is a read-only collection and therefore cannot be used for two-way binding.
class SelectedSyncBehavior
: Behavior<RadGridView>
{
bool _collectionChangedSuspended = false;
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged;
}
/// <summary>
/// Getter/Setter for DependencyProperty, bound to the DataContext's SelectedItems ObservableCollection
/// </summary>
public INotifyCollectionChanged SelectedItems
{
get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
/// <summary>
/// Dependency Property "SelectedItems" is target of binding to DataContext's SelectedItems
/// </summary>
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(SelectedSyncBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
/// <summary>
/// PropertyChanged handler for DependencyProperty "SelectedItems"
/// </summary>
private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
INotifyCollectionChanged collection = args.NewValue as INotifyCollectionChanged;
if (collection != null)
{
// Hook to the Network's SelectedItems
collection.CollectionChanged += (target as SelectedSyncBehavior).ContextSelectedItems_CollectionChanged;
}
}
/// <summary>
/// Will be called, when the Network's SelectedItems collection changes
/// </summary>
void ContextSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_collectionChangedSuspended) return; // Don't react recursively to CollectionChanged events
_collectionChangedSuspended = true;
// Select and unselect items in the grid
if (e.NewItems != null)
foreach (object item in e.NewItems)
AssociatedObject.SelectedItems.Add(item);
if (e.OldItems != null)
foreach (object item in e.OldItems)
AssociatedObject.SelectedItems.Remove(item);
_collectionChangedSuspended = false;
}
/// <summary>
/// Will be called when the GridView's SelectedItems collection changes
/// </summary>
void GridSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_collectionChangedSuspended) return; // Don't react recursively to CollectionChanged events
_collectionChangedSuspended = true;
// Select and unselect items in the DataContext
if (e.NewItems != null)
foreach (object item in e.NewItems)
(SelectedItems as IList).Add(item);
if (e.OldItems != null)
foreach (object item in e.OldItems)
(SelectedItems as IList).Remove(item);
_collectionChangedSuspended = false;
}
}
Use this Behavior with RadGridViews like this:
<i:Interaction.Behaviors>
<behaviors:SelectedSyncBehavior SelectedItems="{Binding ViewModel.SelectedItems}" />
</i:Interaction.Behaviors>

Dean Kuga
- 11,878
- 8
- 54
- 108

Knasterbax
- 7,895
- 1
- 29
- 23
-
3this should be the selected answer! The telerik blogs all seemed to be lacking the complete solution found here. – Michael Nov 17 '14 at 18:11
-
2Don't forget to instantiate the collection SelectedItems property is binding to, wasted 15 minutes on that... – Dean Kuga Oct 17 '17 at 22:00
2
Add a bool IsSelected to the item in your collection:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsSelected { get; set; }
}
private BindableCollection<Customer> _customers;
public BindableCollection<Customer> Customers
{
get { return _customers; }
set
{
_customers = value;
NotifyOfPropertyChange(() => Customers);
}
}

Derek Beattie
- 9,429
- 4
- 30
- 44
-
I know it's been a while, but I'm trying to get this working. Could you show the XAML please as I don't seem to be able to get the binding to work. Alternatively could you make the source available as a download without having to go through bitbucket as I can't get at it there. – Dave Jul 29 '14 at 15:38
-
-
Thanks Derek. I seem to be misunderstanding something. I see you have an IsSelected property on Customer, but I cannot find a binding to it in the XAML. – Dave Jul 31 '14 at 08:30
-
@Dave I believe that's being handled by Telerik control and autogenerated columns. The bool prop IsSelected will display as a checkbox. – Derek Beattie Aug 04 '14 at 16:44
0
Here is a cleaned up copy of @Knasterbax's class with explicit private modifiers and null propagation:
// Behavior for synchronizing Telerik RadDataGrid's SelectedItems collection
// with a SelectedItems collection of the ViewModel.
public class SelectedSyncBehavior : Behavior<RadGridView>
{
private bool collectionChangedSuspended;
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems",
typeof(INotifyCollectionChanged), typeof(SelectedSyncBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectedItems.CollectionChanged += GridSelectedItems_CollectionChanged;
}
public INotifyCollectionChanged SelectedItems
{
get { return (INotifyCollectionChanged)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
var collection = args.NewValue as INotifyCollectionChanged;
if (collection == null) return;
var selectedSyncBehavior = target as SelectedSyncBehavior;
if (selectedSyncBehavior != null) collection.CollectionChanged += selectedSyncBehavior.ContextSelectedItems_CollectionChanged;
}
private void ContextSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (collectionChangedSuspended) return; // Don't react recursively to CollectionChanged events
collectionChangedSuspended = true;
if (e.NewItems != null)
foreach (var item in e.NewItems)
AssociatedObject.SelectedItems.Add(item);
if (e.OldItems != null)
foreach (var item in e.OldItems)
AssociatedObject.SelectedItems.Remove(item);
collectionChangedSuspended = false;
}
private void GridSelectedItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (collectionChangedSuspended) return; // Don't react recursively to CollectionChanged events
collectionChangedSuspended = true;
if (e.NewItems != null)
foreach (var item in e.NewItems)
{
var list = SelectedItems as IList;
list?.Add(item);
}
if (e.OldItems != null)
foreach (var item in e.OldItems)
{
var list = SelectedItems as IList;
list?.Remove(item);
}
collectionChangedSuspended = false;
}
}

Dean Kuga
- 11,878
- 8
- 54
- 108
0
Here's a cleanup version of the answer above. This removes underscores, adds qualifiers, accessors, braces, etc.
public class SelectedItemsBehavior : Behavior<RadGridView>
{
private bool collectionChangedSuspended;
/// <summary>
/// Called after the behavior is attached to an AssociatedObject.
/// </summary>
/// <remarks>
/// Override this to hook up functionality to the AssociatedObject.
/// </remarks>
protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.SelectedItems.CollectionChanged += this.GridSelectedItemsCollectionChanged;
}
/// <summary>
/// Getter/Setter for DependencyProperty, bound to the DataContext's SelectedItems ObservableCollection
/// </summary>
public INotifyCollectionChanged SelectedItems
{
get => (INotifyCollectionChanged)this.GetValue(SelectedItemsProperty);
set => this.SetValue(SelectedItemsProperty, value);
}
/// <summary>
/// Dependency Property "SelectedItems" is target of binding to DataContext's SelectedItems
/// </summary>
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems", typeof(INotifyCollectionChanged), typeof(SelectedItemsBehavior), new PropertyMetadata(OnSelectedItemsPropertyChanged));
/// <summary>
/// PropertyChanged handler for DependencyProperty "SelectedItems"
/// </summary>
private static void OnSelectedItemsPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
INotifyCollectionChanged collection = args.NewValue as INotifyCollectionChanged;
if (collection != null)
{
collection.CollectionChanged += ((SelectedItemsBehavior)target).ContextSelectedItemsCollectionChanged;
}
}
/// <summary>
/// Will be called, when the Network's SelectedItems collection changes
/// </summary>
private void ContextSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (this.collectionChangedSuspended)
{
return;
}
this.collectionChangedSuspended = true;
if (e.NewItems != null)
{
foreach (object item in e.NewItems)
{
this.AssociatedObject.SelectedItems.Add(item);
}
}
if (e.OldItems != null)
{
foreach (object item in e.OldItems)
{
this.AssociatedObject.SelectedItems.Remove(item);
}
}
this.collectionChangedSuspended = false;
}
/// <summary>
/// Will be called when the GridView's SelectedItems collection changes
/// </summary>
private void GridSelectedItemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (this.collectionChangedSuspended)
{
return;
}
this.collectionChangedSuspended = true;
if (e.NewItems != null)
{
foreach (object item in e.NewItems)
{
((IList)this.SelectedItems).Add(item);
}
}
if (e.OldItems != null)
{
foreach (object item in e.OldItems)
{
((IList)this.SelectedItems).Remove(item);
}
}
this.collectionChangedSuspended = false;
}
}

LawMan
- 3,469
- 1
- 29
- 32
-1
There are a situation where you cannot add boolean (ObseravbleCollection for example.
Please take a look at this solution.

Jviaches
- 826
- 3
- 14
- 30
-
Has anybody got that blog post working? I gave it a go and the RadGridView does not even seem to have a SelectedItems property... – GP24 Aug 01 '13 at 08:07