Datagrid.IsSelected Binding and scrolling

vitidev picture vitidev · Jun 21, 2011 · Viewed 7.3k times · Source

I uses MVVM and I bind datagrid to collection with some code:

<DataGrid ItemsSource="{Binding Entites}" AutoGenerateColumns="False" IsSynchronizedWithCurrentItem="True" 
                  SelectedItem="{Binding SelectedEntity}">

And I aslo use binding to IsSelectedProperty using style (RowStyle or ItemContainerStyle)

<DataGrid.RowStyle>
        <Style>
              <Setter Property="DataGridRow.IsSelected" Value="{Binding IsSelectedProperty, Mode=TwoWay}" />                        
        </Style>
</DataGrid.RowStyle>

It works well. But if I scroll datagrid down and up, it stops working.

Answer

Dan J picture Dan J · Jun 22, 2011

I encountered this problem, and the reason was my DataGrid was using virtualization - when you scroll a selected DataGridRow off the screen, the DataGridRow visual element is either destroyed, and a new one created, or - if the DataGrid's VirtualizingStackPanel.VirtualizationMode property is set to Recycling - it is reused for whatever row is entering the viewport.

When either event occurs, the binding between your ViewModel (with its IsSelectedProperty property set) and the DataGridRow (with its IsSelected property set) is broken.

To confirm this is the case, try setting the DataGrid's EnableRowVirtualization property to false.

In my case, I needed the performance required by using virtualization, and ended up implementing selectability using Attached Behaviors: specifically, a click on a row would use a LeftClickCommand attached behavior to invoke a delegate command on the ViewModel that sets IsSelectedProperty. I then used a DataTrigger bound to IsSelectedProperty in the DataGridRow's style to highlight the row.

This solution essentially involves rolling your own selection mechanism, but it was the only way I found to get both row virtualization and MVVM-friendly row selection.