DataGrid row virtualization display issue

24,999

Solution 1

If you are looking for speed ListView Gridview is much much faster (and has less features).

Try disable container recycling.

             <tk:DataGrid x:Name="dataGrid" 
             ItemsSource="{Binding Path=Bookings}" 
             AutoGenerateColumns="False" 
             EnableRowVirtualization="True" 
             EnableColumnVirtualization="True"
             VirtualizingStackPanel.VirtualizationMode="Standard"
             VirtualizingStackPanel.IsVirtualizing="True">

Solution 2

If you turned on Virtualization because the datagrid loading time is terrible, then, here's the solution:

  • turn off virtualization
  • let's assume/call your datagrid's items source binding as "Rows",

    public IEnumerable<Row> Rows {get; set;}
    
  • Add a property to your "Row" class IsVisible and toggle it when you want to load the data (not when UI thread decides to resolve the binding and load each control)

the reason this works, is because when you load the grid, it checks the binding, all row are invisible, so the UI thread doesn't have to spin through all your rows*columns to create them, it can go to the next thing it needs to do. You on the other hand, can detect when is convenient time to turn those rows into visible, when the View.Visibility is visible, when the ViewModel loaded the data from somewhere, etc. So you are in total control. Below I am iterating through my item source (rows) using a task (in a background thread), yet setting Visibility on the UI thread.

   private _isVisible = false;

    /// <summary>
    /// is false by default, for performance when loading first time. 
    /// </summary>
    public bool IsVisible
    {
        get { return _isVisible; }
        set
        {
            if (_isVisible == value)
                return;
            _isVisible = value;
            RaisePropertyChanged(() => IsVisible);
        }
    }
  • In the View, when datagrid is loading don't allow it to hog the UI thread by putting the iteration of rows in the background thread, then set the Visibility to true. Even though you're on the background thread, IsVisible property changed will trigger you to update.

    private void OnGridLoaded(object sender, RoutedEventArgs e)
    {
       //sample bool checks, you might not need them...
       if (firstTimeLoad && !_isDataGridLoaded)
       {
           Task.Factory
               .StartNew(() =>
                {
                    /*first time loading performance tweak*/
                     foreach (var row in _viewModel.Rows)
                        ExeOnUi(() => { row.IsVisible = true; });
    
                     _firstTimeLoad = false;
                 })
       }
    
  • forgot to add ExeOnUi code (you might check access using something else like whateverControl.Dispatcher.CheckAccess, I just use Microsoft.Practices.ServiceLocator):

    static void ExeOnUi (Action action)
    {
        var srv= ServiceLocator.Current.GetInstance<IDispatchService> ();
        if (srv.CheckAccess ())
            action.Invoke ();
        else
            srv.Invoke (action);
    }
    

Solution 3

I just run into similar problem and its resolved after adding UpdateSourceTrigger=PropertyChanged to the binding.

<DataGridTemplateColumn Header="Visible">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <CheckBox IsChecked="{Binding IsShown,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Share:
24,999
WPFNewbie
Author by

WPFNewbie

Updated on May 04, 2020

Comments

  • WPFNewbie
    WPFNewbie almost 4 years

    We currently have a DataGrid that is bound to a DataTable. It also has a template column with a CheckBox in it that we add in programatically. This purpose of this column is track multiple selections in the DataGrid.

    A factory is used to create the CheckBoxes for each row.

    There are quite a few records, so row virtualization is set to true so that the performance is acceptable. However, we're seeing a strange issue where if we check some CheckBoxes on the first 10 rows and then scroll down about 50 rows (the grid has about 10 rows visible at any one time), there are a bunch of other CheckBoxes that appear to be checked at random.

    If we disable row virtualization this problem does not exist (but the performance is terrible). Is there any way around this? Anyone know what we may be doing wrong?