Multi select from datagrid

385
1
Jump to solution
12-17-2023 10:50 AM
mody_buchbinder
Occasional Contributor III

Hello all

This is a pure mvvm question.

I have a datagrid in dockpane. I would like to let the user select many records (using control or shift) so I set the selectionmode to extended (the other option is single).

I set the property in the model view to object so I get something.

When I select one record the property set is activated and I get the selected record.

When I use the shift or control to add more records to the selected the property is not called.

The is working with ListBox where the property is ObservableCollection<MyRecord> but I could not find similar example with DataGrid.

Thanks

 

Thanks

0 Kudos
1 Solution

Accepted Solutions
CharlesMacleod
Esri Regular Contributor

hi mody, this actually proved to be a lot trickier than I expected. Seems Datagrid is not "fully" WPF compliant - it does not have a dependency property for its selected items (the way, say a ListBox or ComboBox has).

https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-pr... gave some options for a solution. I went with this one:

>>One way to to what you want is to register the SelectionChanged event of the DataGrid to update the property of your ViewModel, that stores the selected items.<<

Sub-classing the Datagrid and adding a dependency property for the selected items is a more sophisticated way to go for sure, and is explained in the stackoverflow post, but using the "SelectionChanged" event on the datagrid is v straighforward and this, at least, should get u pointed in the right direction.

I will get this added as a sample to community samples for a complete solution. It's too much code to paste here in its entirety.

 

<UserControl x:Class="DatagridMultiSelect.UI.DataGridDockpaneView"
             ....>
  ....
  <Grid>
    ....

    <DataGrid Grid.Row="1" HorizontalAlignment="Stretch" Height="Auto" 
              ItemsSource="{Binding FeatureData}" VerticalAlignment="Top" 
              x:Name="dataGrid"
              Style="{DynamicResource Esri_DataGrid}"
              HeadersVisibility="Column"
              AutoGenerateColumns="True"
              IsReadOnly="True"
              SelectionMode="Extended"
              SelectionUnit="FullRow"
              CanUserSortColumns="True"
              RowHeaderWidth="0" Margin="0,0,5,0"/>

 

 

Code behind of the view:

 

public partial class DataGridDockpaneView : UserControl {
 public DataGridDockpaneView()
 {
   InitializeComponent();
   this.Loaded += DataGridDockpaneView_Loaded;
 }

 private void DataGridDockpaneView_Loaded(object sender, RoutedEventArgs e)
 {
   var dg_vm = this.DataContext as DataGridDockpaneViewModel;
   dg_vm.SetDataGrid(this.dataGrid);
 }

 

 

and in the dockpane view model:

 

internal class DataGridDockpaneViewModel : DockPane
  {
    private const string _dockPaneID = "DatagridMultiSelect_UI_DataGridDockpane";
    private DataGrid _dataGrid = null;
    private static readonly object _lock = new object();

  internal void SetDataGrid(DataGrid dataGrid) {
    _dataGrid = dataGrid;//wire up the datagrid
    //From:https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-project
    _dataGrid.SelectionChanged += (o, e) => {
        var grid = o as DataGrid;
        var selected = grid.SelectedItems;
        lock (_lock) {
          //"MyRecord" is whatever your custom DataGrid
          //content items are...
          var sel_fd = selected.OfType<MyRecord>().ToList();
          //TODO - use the selection from the grid...
          //
        }
      };
    }
    ...

//Elsewhere:
internal class MyRecord
  {
    //your custom class
  }

 

 

 

 

 

 

 

 

View solution in original post

0 Kudos
1 Reply
CharlesMacleod
Esri Regular Contributor

hi mody, this actually proved to be a lot trickier than I expected. Seems Datagrid is not "fully" WPF compliant - it does not have a dependency property for its selected items (the way, say a ListBox or ComboBox has).

https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-pr... gave some options for a solution. I went with this one:

>>One way to to what you want is to register the SelectionChanged event of the DataGrid to update the property of your ViewModel, that stores the selected items.<<

Sub-classing the Datagrid and adding a dependency property for the selected items is a more sophisticated way to go for sure, and is explained in the stackoverflow post, but using the "SelectionChanged" event on the datagrid is v straighforward and this, at least, should get u pointed in the right direction.

I will get this added as a sample to community samples for a complete solution. It's too much code to paste here in its entirety.

 

<UserControl x:Class="DatagridMultiSelect.UI.DataGridDockpaneView"
             ....>
  ....
  <Grid>
    ....

    <DataGrid Grid.Row="1" HorizontalAlignment="Stretch" Height="Auto" 
              ItemsSource="{Binding FeatureData}" VerticalAlignment="Top" 
              x:Name="dataGrid"
              Style="{DynamicResource Esri_DataGrid}"
              HeadersVisibility="Column"
              AutoGenerateColumns="True"
              IsReadOnly="True"
              SelectionMode="Extended"
              SelectionUnit="FullRow"
              CanUserSortColumns="True"
              RowHeaderWidth="0" Margin="0,0,5,0"/>

 

 

Code behind of the view:

 

public partial class DataGridDockpaneView : UserControl {
 public DataGridDockpaneView()
 {
   InitializeComponent();
   this.Loaded += DataGridDockpaneView_Loaded;
 }

 private void DataGridDockpaneView_Loaded(object sender, RoutedEventArgs e)
 {
   var dg_vm = this.DataContext as DataGridDockpaneViewModel;
   dg_vm.SetDataGrid(this.dataGrid);
 }

 

 

and in the dockpane view model:

 

internal class DataGridDockpaneViewModel : DockPane
  {
    private const string _dockPaneID = "DatagridMultiSelect_UI_DataGridDockpane";
    private DataGrid _dataGrid = null;
    private static readonly object _lock = new object();

  internal void SetDataGrid(DataGrid dataGrid) {
    _dataGrid = dataGrid;//wire up the datagrid
    //From:https://stackoverflow.com/questions/22868445/select-multiple-items-from-a-datagrid-in-an-mvvm-wpf-project
    _dataGrid.SelectionChanged += (o, e) => {
        var grid = o as DataGrid;
        var selected = grid.SelectedItems;
        lock (_lock) {
          //"MyRecord" is whatever your custom DataGrid
          //content items are...
          var sel_fd = selected.OfType<MyRecord>().ToList();
          //TODO - use the selection from the grid...
          //
        }
      };
    }
    ...

//Elsewhere:
internal class MyRecord
  {
    //your custom class
  }

 

 

 

 

 

 

 

 

0 Kudos