winui-3windows-community-toolkit

How to implement mvvm selecteditems in Communitytoolkit datagrid


I'm using communitytoolkit datagrid and I'd like implent the selecteditems property in mvvm environment. I created a custom attachedproperty, but the selecteditems property of the datagrid, not inherit from INotifyCollectionChanged that I want to use for to reset the collection by code.

Thi is my attached property:

        public class SelectedItemsAttachedProperty
        {
           public static IList GetSelectedItems(DependencyObject obj)
           {
              return (IList)obj.GetValue(SelectedItemsProperty);
           }

           public static void SetSelectedItems(DependencyObject obj, IList value)
           {
              obj.SetValue(SelectedItemsProperty, value);
           }

           public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(SelectedItemsAttachedProperty), new PropertyMetadata(new ObservableCollection<object>(), SelectedItemsChanged));

           private static void SelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
           {
               if(d is DataGrid)
               {
                   DataGrid dg = d as DataGrid;
                   dg.SelectionChanged += (sender, e) =>
                   {
                       DataGrid it = sender as DataGrid;
                       foreach (var item in e.AddedItems)
                       {
                          it.SelectedItems.Add(item);
                       }

                       foreach (var item in e.RemovedItems)
                       {
                          it.SelectedItems.Remove(item);
                       }                    
                   };

                   var oc = dg.SelectedItems as INotifyCollectionChanged;

                   oc.CollectionChanged += (o, e) =>
                   {
                       if (e.Action == NotifyCollectionChangedAction.Reset)
                       {
                           dg.SelectedItems.Clear();
                       }
                   };
               }
           }
    }

Thanks


Solution

  • Instead of an attached property, you can create custom control:

    public class DataGridEx : DataGrid
    {
        public static readonly DependencyProperty SelectedItemsProperty =
            DependencyProperty.Register(
                nameof(SelectedItems),
                typeof(IList),
                typeof(DataGridEx),
                new PropertyMetadata(new ObservableCollection<object>()));
    
        public DataGridEx() : base()
        {
            this.SelectionChanged += DataGridEx_SelectionChanged;
        }
    
        public new IList SelectedItems
        {
            get { return (IList)GetValue(SelectedItemsProperty); }
            set { SetValue(SelectedItemsProperty, value); }
        }
    
        private void DataGridEx_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            foreach (object item in e.RemovedItems)
            {
                SelectedItems.Remove(item);
            }
    
            foreach (object item in e.AddedItems)
            {
                SelectedItems.Add(item);
            }
        }
    }
    

    UPDATE

    You can get CollectionChanged events like this:

    private void DataGridExControl_Loaded(object sender, RoutedEventArgs e)
    {
        if (sender is not DataGridEx dataGridEx ||
            dataGridEx.SelectedItems is not INotifyCollectionChanged selectedItems)
        {
            return;
        }
    
        selectedItems.CollectionChanged += SelectedItems_CollectionChanged;
    }
    
    private void SelectedItems_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
    {
    }