We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Very slow selection of rows in sfDataGrid

My current application is being designed to work with large datasets. Sometimes I have tens of thousands of rows in the datagrid. It all works great and fast with virtualization enabled, except for the row selection. When I select all rows to delete or process them, the grid freezes for a long time. In my latest measurement, when I tried selecting 64000  rows, it took 66000 milliseconds to do so, and I have a reasonably fast computer. (For reference, I need the same amount of time to delete these 64000 rows from 15 database tables using EF6, as well as purge any related binary files from disk.)

I believe sfDataGrid's selection implementation may be bugged or suboptimal, because the previous grid I was using before (DevExp) selected the same numbers of rows in a matter of milliseconds. So I would like to ask you to look into the implementation and produce a fix, if possible. Sadly, large selections are unusable at the monent.

This is the method I use for selecting rows:

sfDataGrid.SelectionController.ClearSelections(false); 
sfDataGrid.SelectRows(sfDataGrid.GetFirstDataRowIndex()sfDataGrid.GetLastDataRowIndex());


9 Replies

JG Jai Ganesh S Syncfusion Team June 2, 2016 02:25 PM UTC

Hi Andrey, 
You can improve the performance when you select the rows by customize the GridSelectionController and override the SelectRows method like below, 
this.datagrid.SelectionController = new GridSelectionControllerExt(datagrid); 
 
  public class GridSelectionControllerExt : GridSelectionController 
    { 
        SfDataGrid datagrid; 
        public GridSelectionControllerExt(SfDataGrid dataGrid) 
            : base(dataGrid) 
        { 
            datagrid = dataGrid; 
        } 
 
        public override void SelectRows(int startRowIndex, int endRowIndex) 
        { 
            if (startRowIndex < 0 || endRowIndex < 0) 
                return; 
 
            if (startRowIndex > endRowIndex) 
            { 
                var temp = startRowIndex; 
                startRowIndex = endRowIndex; 
                endRowIndex = temp; 
            } 
 
            if (this.DataGrid.SelectionMode == GridSelectionMode.None || 
                this.DataGrid.SelectionMode == GridSelectionMode.Single) 
                return; 
 
            var isSelectedRowsContains = this.SelectedRows.Any(); 
 
            this.SuspendUpdates(); 
            var addedItem = new List<object>(); 
            int rowIndex = startRowIndex; 
#if !WP 
                        ResetParentGridSelection(); 
#endif 
 
            var rowIndexes = this.GetRowIndexes(); 
 
            var selectedrowindex = this.datagrid.ResolveToRowIndex(this.datagrid.SelectedIndex); 
 
           // if (!this.DataGrid.GridModel.HasGroup) 
            { 
                int recordindex = 0; 
                GridRowInfo rowInfo = null; 
                for (int i = rowIndex; i <= endRowIndex; i++) 
                { 
                    object rowData = this.DataGrid.GetRecordAtRowIndex(rowIndex); 
                    rowIndex = this.DataGrid.ResolveToRowIndex(recordindex); 
                    if (!rowIndexes.Contains(rowIndex)) 
                    { 
                        this.DataGrid.SelectedItems.Add(rowData); 
                        this.SelectedRows.Add(GetGridSelectedRow(rowIndex)); 
                    } 
                    recordindex++; 
                } 
            } 
            this.ShowAllRowSelectionBorder(); 
            if (!isSelectedRowsContains) 
            { 
                this.RefreshSelectedIndex(); 
            } 
            this.ResumeUpdates(); 
        } 
        private void ResetParentGridSelection() 
        { 
            if (!(this.DataGrid is DetailsViewDataGrid)) 
                return; 
            var parentDataGrid = this.DataGrid.GetParentDataGrid(); 
            var selectionController = parentDataGrid.SelectionController as GridSelectionControllerExt; 
            var removedItems = selectionController.SelectedRows.ToList<object>(); 
            var rowIndex = parentDataGrid.GetGridDetailsViewRowIndex(this.DataGrid as DetailsViewDataGrid); 
            selectionController.ResetSelection(rowIndex, removedItems, true); 
             
        } 
 
        protected internal void ResetSelection(int rowIndex, List<object> removedItems, bool setFocuForGrid = true) 
        { 
            var addedItems = new List<object>(); 
            var rowInfo = this.GetGridSelectedRow(rowIndex); 
 
            if (!this.SelectedRows.Contains(rowInfo)) 
                addedItems.Add(rowInfo); 
 
           
            this.DataGrid.HideRowFocusBorder(); 
            if (removedItems != null && removedItems.Count > 0) 
            { 
                this.RemoveSelection(rowIndex, removedItems, SelectionReason.GridOperations); 
            } 
 
            if (addedItems.Count > 0) 
                this.AddSelection(addedItems, SelectionReason.GridOperations); 
 
        } 
 
 
        private void RefreshSelectedIndex() 
        { 
            this.DataGrid.SelectedIndex = this.SelectedRows.Count > 0 ? this.DataGrid.ResolveToRecordIndex(this.SelectedRows[0].RowIndex) : -1; 
            this.DataGrid.SelectedItem = this.DataGrid.SelectedItems.Count > 0 ? this.DataGrid.SelectedItems[0] : null; 
        } 
        internal List<int> GetRowIndexes() 
        { 
            return this.datagrid.SelectionController.SelectedRows.Select(rowinfo => rowinfo.RowIndex).ToList(); 
        } 
        
    } 
 
Sample: 
Regards, 
Jai Ganesh S 



AN Andrey June 2, 2016 07:19 PM UTC

Jai Ganesh S,

thank you for the suggested solution. I was able to reduce the selection time of 100,000 rows from 100,000ms to 100ms, i.e. it is now faster by a thousand times. I commented out lines that add rowData objects to DataGrid.SelectedItems. Now I can access the data items using this logic: var selectedItems = sfDataGrid.SelectionController.SelectedRows.Select(x => x.RowData as MyPocoClass).Select(x => x.Id); It is way better for speed and memory.

I still have the problem of slow selection when selecting by SHIFT-clicking on the first and last grid rows. It seems to use another method than the overridden SelectRows. Please advise on how I can fix the Shift-click selection as well. Thank you!


 public override void SelectRows(int startRowIndex, int endRowIndex)
        {
                if (startRowIndex < 0 || endRowIndex < 0)
                return;

            if (startRowIndex > endRowIndex)
            {
                var temp = startRowIndex;
                startRowIndex = endRowIndex;
                endRowIndex = temp;
            }

            if (this.DataGrid.SelectionMode == GridSelectionMode.None ||
                this.DataGrid.SelectionMode == GridSelectionMode.Single)
                return;

            var isSelectedRowsContains = this.SelectedRows.Any();

            this.SuspendUpdates();
           
        //    var addedItem = new List<object>();
            int rowIndex = startRowIndex;

           // ResetParentGridSelection();

            var rowIndexes = this.GetSelectedRowIndexes();

            //      var selectedrowindex = this.DataGrid.ResolveToRowIndex(this.DataGrid.SelectedIndex);

            // if (!this.DataGrid.GridModel.HasGroup)
           //{
                int recordindex = 0;
                //    GridRowInfo rowInfo = null;
                for (int i = rowIndex; i <= endRowIndex; i++)
                {
                    //object rowData = this.DataGrid.GetRecordAtRowIndex(rowIndex);                <= This is problematic
                    rowIndex = this.DataGrid.ResolveToRowIndex(recordindex);
                    if (!rowIndexes.Contains(rowIndex))
                    {
                        //this.DataGrid.SelectedItems.Add(rowData );                                           <= This is problematic
                        this.SelectedRows.Add(GetGridSelectedRow(rowIndex));
                    }
                    recordindex++;
                }
           // }

            this.ShowAllRowSelectionBorder();
            if (!isSelectedRowsContains)
            {
                this.RefreshSelectedIndex();
            }
            this.ResumeUpdates();
          
        }


JG Jai Ganesh S Syncfusion Team June 3, 2016 01:26 PM UTC

Hi Andrey, 
 
You can achieve your requirement to improve the performance when you shift selecting the first and last grid rows by overriding the ProcessPoinerReleased event like below, 
 
   protected override void ProcessPointerReleased(MouseButtonEventArgs args, Syncfusion.UI.Xaml.ScrollAxis.RowColumnIndex rowColumnIndex) 
        { 
            if (SelectionHelper.CheckShiftKeyPressed()) 
            { 
                this.SelectRows(this.PressedRowColumnIndex.RowIndex, rowColumnIndex.RowIndex); 
            } 
 
            else 
                base.ProcessPointerReleased(args, rowColumnIndex); 
        } 
 
 
 
Regards, 
Jai Ganesh S 



TR Thiago Renan Gomes June 18, 2019 06:34 PM UTC

I have made a very small change to improve the performance when the datagrid is already selecteded.

...
var rowIndexes = this.GetRowIndexes();
rowIndexes.Sort();
...
if (rowIndexes.BinarySearch(rowIndex) < 0)
...

Thanks for the help.


FP Farjana Parveen Ayubb Syncfusion Team June 19, 2019 11:02 AM UTC

Hi Thiago ,

 

We are glad to know that the reported problem has been resolved at your end. Please let us know if you have any further queries on this. We are happy to help you.

 

Regards,

Farjana Parveen A

 



TR Thiago Renan Gomes July 8, 2019 04:53 PM UTC

Hello,


I'm having some problems with the select all function, the performance is very low when I need to select more than 20 thousand records, I get to cases where I need to select millions and how the function uses the screen thread, this generates a performance problem and feedback.


I would like to help to create an override for the selectall function that allows me to work with a large amount of records, would it be possible?



AK Adhikesevan Kothandaraman Syncfusion Team July 9, 2019 01:38 PM UTC

Hi Andrey, 

Thanks for your update. 

If you want to get the process the large records on the SelectAll operation, you can use the custom selection controller and override the SelectAll method. Please refer to the following code snippet for your reference, 

Code Snippet: 
this.SfDataGrid.SelectionController = new SelectionControllerExt(this.SfDataGrid); 
public class SelectionControllerExt : GridSelectionController 
{ 
    public SelectionControllerExt(SfDataGrid sfDataGrid) 
        :base(sfDataGrid) 
    { 
 
    } 
 
    public override void SelectAll(bool canFocus = true) 
    { 
        //To do.. 
        base.SelectAll(canFocus); 
    } 
} 
 
Regards, 
Adhi 



TR Thiago Renan Gomes July 16, 2019 11:42 AM UTC


Hi,

Thanks for the answer, this reference I already had in previous answers, I would like to know with what I can consult, all the operations and lists that I must complete so that all the functionalities of the grid continue to work.

Thank you for your help.


FP Farjana Parveen Ayubb Syncfusion Team July 17, 2019 10:06 AM UTC

Hi Thiago, 
 
Thank you for your update. 
 
We are regret to inform you that we can’t able to understand your query. So can you please share the more details regarding your query that will help us to provide the better solution? 
 
Regards, 
Farjana Parveen A 


Loader.
Live Chat Icon For mobile
Up arrow icon