I am currently using the radgridview to hold 246k rows and 13 columns of data. I extened the radgridview so that I could handle many othe requiremnts that I have. Even before extending the control I have noticed significant problems in selecting multiple rows. For instance in the application I just described there is not the much data present in the grid. To get the data I progromatically build a datatable and then attach it to the grid as the datasource. Then I try to select multiple rows via shift + click and it will take over 25 seconds to select 100k rows. I am not sure what is exactly causing this problem but to make things even worse when I am done with my selection and would like to lose it or make another one it takes just as long for the grid do remove the selection from the selectedrows property. Is there anything that I can do to make this simple process respond in a reasonable manner?
I am using winforms controls 2011.1.11.419 and visual studio 2010 vb.net
I am using winforms controls 2011.1.11.419 and visual studio 2010 vb.net
8 Answers, 1 is accepted
0
Hello Nick,
Thank you for bringing our attention to this issue.
Yes, I can confirm that multiple row selection can become slow when there is a large number of rows. I added this issue in our issue tracking system and it will be addressed in our upcoming release. I updated also your Telerik points for reporting it.
Due to the nature of the issue I am not able to provide a suitable work around. However, if this is a show stopper for you we could prepare an internal build where the issue is addressed.
Should you have any other questions, do not hesitate to contact us.
Regards,
Nikolay
the Telerik team
Thank you for bringing our attention to this issue.
Yes, I can confirm that multiple row selection can become slow when there is a large number of rows. I added this issue in our issue tracking system and it will be addressed in our upcoming release. I updated also your Telerik points for reporting it.
Due to the nature of the issue I am not able to provide a suitable work around. However, if this is a show stopper for you we could prepare an internal build where the issue is addressed.
Should you have any other questions, do not hesitate to contact us.
Regards,
Nikolay
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
nhalm
Top achievements
Rank 1
answered on 13 Sep 2011, 04:14 PM
Thank you for the reply. I actually updated to q2 2011 last night and the seems to work a slightly better. From what I can tell the row collection is just iterated through and the .isSelected flag is set on the gridrowinfo. I can see how it is possible for this to be slow but this actually brings up another issue that I have been having with the gridview. My other issue is iterating the the rowcollection is quite slow. I have tried both For i as Integer =0 to grd.rows.count-1 and also for each row in grd.rows and I can say the performance seems improved using For i as Integer.
It would be easier if I had the option to get the datasource table rows and manipulate them, and probably faster. I know I can use the databounditem property of the row but that is still requiring me to iterated through the selected rows.
I don't really know the answer I just know that manipulating large amounts of data through gridfunctions is very slow.
It would be easier if I had the option to get the datasource table rows and manipulate them, and probably faster. I know I can use the databounditem property of the row but that is still requiring me to iterated through the selected rows.
I don't really know the answer I just know that manipulating large amounts of data through gridfunctions is very slow.
0
Hi Nick Halm,
Thank you for writing me back.
Setting the IsSelected property causes RadGridView to update other row states and that is what causes the issue. As I said, we will optimize the update process in our upcoming release. Our fix will affect the selection operations when using the user interface. For example when clicking a row with the mouse.
I tested the following case: a RadGridView containing 400 000 rows. My test indicates that iterating the Rows collection takes ~582 milliseconds. However, this process may become slow when updating cell values or when you change the IsSelected property. If this is the case, I recommend the following approach:
If this does not help, please send me your code and I will try to optimize it.
I am looking forward to your reply.
Regards,
Jack
the Telerik team
Thank you for writing me back.
Setting the IsSelected property causes RadGridView to update other row states and that is what causes the issue. As I said, we will optimize the update process in our upcoming release. Our fix will affect the selection operations when using the user interface. For example when clicking a row with the mouse.
I tested the following case: a RadGridView containing 400 000 rows. My test indicates that iterating the Rows collection takes ~582 milliseconds. However, this process may become slow when updating cell values or when you change the IsSelected property. If this is the case, I recommend the following approach:
For
i
As
Integer
= 0
To
Me
.radGridView1.ChildRows.Count - 1
Dim
row
As
GridViewRowInfo =
Me
.radGridView1.ChildRows(i)
row.SuspendPropertyNotifications()
row.IsSelected =
True
row.ResumePropertyNotifications()
Next
Me
.radGridView1.TableElement.ViewElement.ClearRows()
Me
.radGridView1.TableElement.ViewElement.UpdateRows()
If this does not help, please send me your code and I will try to optimize it.
I am looking forward to your reply.
Regards,
Jack
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
0
nhalm
Top achievements
Rank 1
answered on 20 Sep 2011, 03:56 AM
Thank you again for your help. I have tried your solution to try and speed up the problem that I have been experiencing. I would like to send you some code with this reply to see what you think of my solution and if there are any glaring problems. First of all I should be more specific of what I am trying to accomplish. I need the grid to do a few more things including, highlight all changes, keep track of all modified, added, deleted, and error rows and use custom row formatting and filters to display them. I also have the requirement to handle copy and past from one grid to another or to the same grid, and to be able to change one column on selected rows simultaneously. To accomplish all these things I have simply inherited the RadGridView, added custom properties, functions and handlers. One thing that I found along the way is that selecting multiple rows is slow, I am happy to report that after updating to version 2011 Q2 that speed is actually dramatically improved, so that is no longer one of my concerns. I believe that I have an acceptable solution to the copy and paste requirement and row/cell formatting. Right now I am still trying to handle two problems. The first is changing the same column on selected rows. The fastest way I have found to do this is to actually add a column to the datasource table so that I can easily refernce that specific row outside of the grid itself. Included is some code to do that but basically what I do is in the Datasource property before it gets set I add some columns to the table and then enumerate the column rowid. Then in the CellValueChanged event I look to see if more that one row is selected and if so change each column to the same value. The last step that takes care of making the cell formatting possible is the Datasource.ColumnChanged event that adds the original value and changed cell index into an object column that holds a hash table. I don't know if this makes that much sense or not, but simply iterating the RowsSelectedCollection and changing those values was taking about 50 milliseconds per cell when the selected rows collection is about 50k rows and the datasource is 250k rows. I can actually live with this solution but there is on more problem that it brings up. How do I keep that form from flickering or going white completely during a long running event like this? Preferably I would love to have a progress bar for something that is going to take this long. Although roughyl 38 seconds to change 50k rows doesn't seem like much, that does not include any of the time it takes to commit and audit each change to a database, that is why I am looking to save milliseconds and reduce screen lag. Thanks again for any help.
Public
Shadows
Property
DataSource()
As
Object
Get
Return
MyBase
.DataSource
End
Get
Set
(
ByVal
value
As
Object
)
If
value
Is
Nothing
Then
MyBase
.DataSource =
Nothing
Exit
Property
End
If
Dim
table = TryCast(value, DataTable)
If
table
Is
Nothing
Then
MyBase
.DataSource = value
Exit
Property
End
If
If
Not
table.Columns.Contains(conADDED)
Then
table.Columns.Add(conADDED, System.Type.
GetType
(
"System.String"
))
End
If
If
Not
table.Columns.Contains(conDELETED)
Then
table.Columns.Add(conDELETED, System.Type.
GetType
(
"System.String"
))
End
If
If
Not
table.Columns.Contains(conMODIFIED)
Then
table.Columns.Add(conMODIFIED, System.Type.
GetType
(
"System.String"
))
End
If
If
Not
table.Columns.Contains(conERRORROW)
Then
table.Columns.Add(conERRORROW, System.Type.
GetType
(
"System.String"
))
End
If
If
Not
table.Columns.Contains(conCHANGESLINK)
Then
table.Columns.Add(conCHANGESLINK, System.Type.
GetType
(
"System.Object"
))
End
If
If
Not
table.Columns.Contains(conROWID)
Then
table.Columns.Add(conROWID, System.Type.
GetType
(
"System.Int32"
))
End
If
For
i
As
Integer
= 0
To
table.Rows.Count - 1
table.Rows(i).Item(conROWID) = i
Next
AddHandler
table.ColumnChanging,
AddressOf
Datasource_ColumnChanging
MyBase
.DataSource = table
End
Set
End
Property
Private
Sub
Datasource_ColumnChanging(
ByVal
sender
As
Object
,
ByVal
e
As
DataColumnChangeEventArgs)
Dim
tim
As
New
Stopwatch
tim.Start()
If
_skipColumns.Contains(e.Column.ColumnName)
Then
Exit
Sub
Dim
hTable
As
Hashtable
hTable = TryCast(e.Row.Item(conCHANGESLINK), Hashtable)
If
hTable
Is
Nothing
Then
hTable =
New
Hashtable
hTable.Add(e.Column.ColumnName, e.Row.Item(e.Column))
e.Row.Item(conCHANGESLINK) = hTable
e.Row.Item(conMODIFIED) = conCHFLAG
Else
If
hTable.Contains(e.Column.ColumnName) =
False
Then
hTable.Add(e.Column.ColumnName, e.Row.Item(e.Column))
e.Row.Item(conCHANGESLINK) = hTable
e.Row.Item(conMODIFIED) = conCHFLAG
Else
If
e.ProposedValue = hTable.Item(e.Column.ColumnName)
Then
hTable.Remove(e.Column.ColumnName)
If
hTable.Count = 0
Then
e.Row.Item(conMODIFIED) = conUCHFLAG
End
If
End
If
End
If
End
If
tim.
Stop
()
Debug.Print(
"time to change one cell = {0}:{1}:{2}"
, tim.Elapsed.Minutes, tim.Elapsed.Seconds, tim.Elapsed.Milliseconds)
End
Sub
Private
Sub
lsGridView_CellValueChanged(sender
As
Object
, e
As
Telerik.WinControls.UI.GridViewCellEventArgs)
Handles
Me
.CellValueChanged
If
_isUpdating
Then
Exit
Sub
If
Me
.SelectedRows.Count > 1
Then
RemoveHandler
Me
.CellValueChanged,
AddressOf
lsGridView_CellValueChanged
_isUpdating =
True
UseWaitCursor =
True
Dim
colname
As
String
= e.Column.FieldName
Dim
indexes(
Me
.SelectedRows.Count - 1)
As
Integer
For
i
As
Integer
= 0
To
Me
.SelectedRows.Count - 1
indexes(i) =
Me
.SelectedRows(i).Cells(conROWID).Value
Next
Dim
oldPK
As
DataColumn() = DataSource.primarykey
Dim
rw
As
DataRow
DataSource.primarykey =
New
DataColumn() {DataSource.columns(conROWID)}
Dim
tim
As
New
Stopwatch
tim.Start()
Me
.BeginUpdate()
For
k
As
Integer
= 0
To
indexes.Count - 1
rw = DataSource.rows.find(indexes(k))
rw.Item(colname) = e.Value
Next
Me
.EndUpdate()
Me
.TableElement.ViewElement.ClearRows()
Me
.TableElement.ViewElement.UpdateRows()
tim.
Stop
()
Debug.Print(
"time to change all = {0}:{1}:{2}"
, tim.Elapsed.Minutes, tim.Elapsed.Seconds, tim.Elapsed.Milliseconds)
DataSource.primarykey = oldPK
_isUpdating =
False
UseWaitCursor =
False
AddHandler
Me
.CellValueChanged,
AddressOf
lsGridView_CellValueChanged
End
If
End
Sub
0
nhalm
Top achievements
Rank 1
answered on 20 Sep 2011, 04:06 AM
I actually took the timer out of the Datasource_ColumnsChanging Event and the speed dropped dramatically. to just less than 10 seconds to update 48k rows. I shouldn't have left that in there I guess. Thanks for your help.
Nick
Nick
0
nhalm
Top achievements
Rank 1
answered on 21 Sep 2011, 04:49 PM
Is there any update on this?
I have found that while ctrl-A to select all rows is quite fast now using the shift-click method is still incredibly slow taking almost a minutes to select 70k rows. The other problem is that even after making my selection it still takes a long time to un-select those rows. I really need some help on this. I tried your example using the SuspendPropertyNotification but, since I am not programatically selecting rows outside the grid I don't know how I could make that work.
I have found that while ctrl-A to select all rows is quite fast now using the shift-click method is still incredibly slow taking almost a minutes to select 70k rows. The other problem is that even after making my selection it still takes a long time to un-select those rows. I really need some help on this. I tried your example using the SuspendPropertyNotification but, since I am not programatically selecting rows outside the grid I don't know how I could make that work.
0
nhalm
Top achievements
Rank 1
answered on 21 Sep 2011, 07:05 PM
I have found a way to removed the selectedrows quickly now. This is what I am using for that:
The first part works great. The second part is not so great. I am trying to speed up the shift_click method of selecting rows and altought this second part iterates through the rows very quickly the selectedRowsCollection does not update. After the operation Me.SelectedRows.Count = 1. If I remove the row.suspendPropertyNotifications and the subsequent call it will update the collection but the speed is nothing to be proud of.
Also I still need a way to prevent the application from flickering and turning white or worse, throwing the "This Application has stopped responding." message.
Thanks for any help!
Nick
Private Sub lsGridView_CurrentRowChanging(sender As Object, e As Telerik.WinControls.UI.CurrentRowChangingEventArgs) Handles Me.CurrentRowChanging
If Me.SelectedRows.Count > 1 Then
For i As Integer = 0 To Me.ChildRows.Count - 1
Dim row As Telerik.WinControls.UI.GridViewRowInfo = Me.ChildRows(i)
row.SuspendPropertyNotifications()
row.IsSelected = False
row.ResumePropertyNotifications()
Next
Me.TableElement.ViewElement.ClearRows()
Me.TableElement.ViewElement.UpdateRows()
Else
If My.Computer.Keyboard.ShiftKeyDown AndAlso Me.SelectedRows.Count = 1 Then
Dim rstart As Integer
Dim rend As Integer
If e.CurrentRow.Index > e.OldRow.Index Then
rstart = e.NewRow.Index
rend = e.CurrentRow.Index
Else
rstart = e.CurrentRow.Index
rend = e.NewRow.Index
End If
For i As Integer = rstart To rend
Dim row As Telerik.WinControls.UI.GridViewRowInfo = Me.ChildRows(i)
row.SuspendPropertyNotifications()
row.IsSelected = True
row.ResumePropertyNotifications()
Next
Me.TableElement.ViewElement.ClearRows()
Me.TableElement.ViewElement.UpdateRows()
End If
End If
End Sub
The first part works great. The second part is not so great. I am trying to speed up the shift_click method of selecting rows and altought this second part iterates through the rows very quickly the selectedRowsCollection does not update. After the operation Me.SelectedRows.Count = 1. If I remove the row.suspendPropertyNotifications and the subsequent call it will update the collection but the speed is nothing to be proud of.
Also I still need a way to prevent the application from flickering and turning white or worse, throwing the "This Application has stopped responding." message.
Thanks for any help!
Nick
0
Hello Nick,
Thank you for the description of your issue and for the code. I am not sure that I fully understand what you want to achieve, but I looked into your code and noticed you are applying very often the following code snippet:
Calling the ClearRows and UpdateRows methods causes RadGridView to reset all of its visual elements. The same is valid for the EndUpdate method. It is not necessary to call these methods and you could change the code the following way:
If your requirement is to change other column values based on the changed value, you could optimize this code further:
Here is the modified version of your last code snippet:
Now it should run much faster. Could you please confirm that? If you continue to experience a slow down, please open a new support ticket, send me your application and I will try to optimize it.
I am looking forward to your reply.
Best wishes,
Svett
the Telerik team
Thank you for the description of your issue and for the code. I am not sure that I fully understand what you want to achieve, but I looked into your code and noticed you are applying very often the following code snippet:
Me
.TableElement.ViewElement.ClearRows()
Me
.TableElement.ViewElement.UpdateRows()
Calling the ClearRows and UpdateRows methods causes RadGridView to reset all of its visual elements. The same is valid for the EndUpdate method. It is not necessary to call these methods and you could change the code the following way:
Me
.BeginUpdate()
'Your update operation here
Me
.EndUpdate(
False
)
Me
.RadGridView1.TableElement.Update(GridUINotifyAction.DataChanged)
If your requirement is to change other column values based on the changed value, you could optimize this code further:
Me
.BeginUpdate()
For
k
As
Integer
= 0
To
indexes.Count - 1
Me
.SelectedRows(k).Cells(conROWID).Value = e.Value
Next
Me
.EndUpdate(
False
)
Me
.RadGridView1.TableElement.Update(GridUINotifyAction.DataChanged)
Here is the modified version of your last code snippet:
Private
Sub
lsGridView_CurrentRowChanging(sender
As
Object
, e
As
Telerik.WinControls.UI.CurrentRowChangingEventArgs)
Handles
Me
.CurrentRowChanging
If
Me
.SelectedRows.Count > 1
Then
Me
.BeginUpdate()
For
i
As
Integer
= 0
To
Me
.ChildRows.Count - 1
Dim
row
As
Telerik.WinControls.UI.GridViewRowInfo =
Me
.ChildRows(i)
row.SuspendPropertyNotifications()
row.IsSelected =
False
row.ResumePropertyNotifications()
Next
Me
.EndUpdate(
False
)
Me
.RadGridView1.TableElement.Update(GridUINotifyAction.DataChanged)
Else
If
My.Computer.Keyboard.ShiftKeyDown
AndAlso
Me
.SelectedRows.Count = 1
Then
Dim
rstart
As
Integer
Dim
rend
As
Integer
If
e.CurrentRow.Index > e.OldRow.Index
Then
rstart = e.NewRow.Index
rend = e.CurrentRow.Index
Else
rstart = e.CurrentRow.Index
rend = e.NewRow.Index
End
If
Me
.BeginUpdate()
For
i
As
Integer
= rstart
To
rend
Dim
row
As
Telerik.WinControls.UI.GridViewRowInfo =
Me
.ChildRows(i)
row.SuspendPropertyNotifications()
row.IsSelected =
True
row.ResumePropertyNotifications()
Next
Me
.EndUpdate(
False
)
Me
.RadGridView1.TableElement.Update(GridUINotifyAction.DataChanged)
End
If
End
If
End
Sub
Now it should run much faster. Could you please confirm that? If you continue to experience a slow down, please open a new support ticket, send me your application and I will try to optimize it.
I am looking forward to your reply.
Best wishes,
Svett
the Telerik team
Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>