Home > Blockchain >  Wpf MutliSelect DataGrid with custom datagrid
Wpf MutliSelect DataGrid with custom datagrid

Time:09-15

I'm aware that there are several posts about how to implement datagrid mutliselection.

I've found the open issue on Github (https://github.com/dotnet/wpf/issues/3140). The user ice1e0 mentioned a solution with a CustomDataGrid class.

public class CustomDataGrid : DataGrid
{
        public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register(nameof(SelectedItems), typeof(IList), typeof(CustomDataGrid), new PropertyMetadata(default(IList), OnSelectedItemsPropertyChanged));

        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            SetValue(SelectedItemsProperty, base.SelectedItems);
        }

        public new IList SelectedItems
        {
            get => (IList)GetValue(SelectedItemsProperty);
            set => throw new Exception("This property is read-only. To bind to it you must use 'Mode=OneWayToSource'.");
        }

        private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((CustomDataGrid)d).OnSelectedItemsChanged((IList)e.OldValue, (IList)e.NewValue);
        }

        protected virtual void OnSelectedItemsChanged(IList oldSelectedItems, IList newSelectedItems)
        {
        }
}

So, I tried to implement it, so I copied the class. And my xaml looks something like that:

<Project1:CustomDataGrid ItemsSource="{Binding Data}" SelectionMode="Extended" SelectionUnit="FullRow" IsReadOnly="True" SelectedItems="{Binding SelectedComputers, Mode=OneWayToSource}" />

and my ViewModel:

[ObservableProperty]
ObservableCollection<string> _selectedComputers;

I use CommunityToolkit.Mvvm (v8.0).

It compiles but SelectedComputers is null, after I select one or multiple items.

UPDATE:

The issue seems that

        void CustomDataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.SelectedItemsList = this.SelectedItems;
        }

doesn't work. SelectedItemsList is always null. The problem is mentioned in the other thread: Select multiple items from a DataGrid in an MVVM WPF project

The suggested solution by M463:

this.SelectedItemsList = this.SelectedItems; did not work for me, as SelectedItemsList was always set to null. However, changing the code to foreach (var item in this.SelectedItems) { this.SelectedItemsList.Add(item); } did the trick. Please note, that this requires you to call this.SelectedItemsList.Clear(); in advance, so the items of SelectedItemsList will not get duplicated.

When I try the solution, after selected a row the application crashes with the error:

System.ArgumentException: 'The value "System.Data.DataRowView" is not of type "System.String" and cannot be used in this generic collection.
Parameter name: value'

CodePudding user response:

You cannot mix types.

If you Data is a DataView, SelectedItems cannot be bound to an ObservableCollection<string> because you cannot add a (selected) DataRowView to an ObservableCollection<string>.

Also, you cannot set an ObservableCollection<string> property to anything else than an ObservableCollection<string>. That's why the value in the setter of the source property comes in as null when you try to set it to an IList using SetValue.

If you make SelectedComputers an IList, you should see it being set from the control:

[ObservableProperty]
IList _selectedComputers;

The other option is obviously to change the type of the dependency property.

  • Related