Hi,
I use a wingrid which auto refreshes every 5 seconds.The problem that I face is when the user scrolls down the grid, suddenly the grid refreshes and moves back up to the top.I want the grid to stay in the same scroll area after refreshing.I set the the first row as active row after every refresh.
So how to save the current scroll position and load the same back after refresh?Or can anyone suggest a better solution?
Thanks,
Abja
I can't avoid refreshing the data, it is a requirement to have fresh data each x seconds.
When rows are not grouped by it works, when rows are grouped by and it's a datarow as first row it also works. But when rows are grouped by and the firstrow is Grouped By row it doesn't, the grid is displayed with the first row of the grid on top (<> The first row displayed).
The correct row is found (I seperate the description with "(" seperator to be shure that the number of items (datarows) doesn't change the fact that that groupedbyrow is the first one, like this :
if (FirstRowDescription != string.Empty) { char[] seperators = { '(' }; if (row.Description.Split(seperators)[0] == FirstRowDescription.Split(seperators)[0]) { ok = true; } }
The correct row is found and stored:
if (CheckIfRowIsFirstRow(row, pkValuesFirstRow)) { this.DisplayLayout.RowScrollRegions[0].FirstRow = row; FirstRow = row; setFirstRow = true; DoSearch = false; }
Here this.DisplayLayout.RowScrollRegions[0].FirstRow has the correct row!
This method is called in the ctlTaskDataGrid.cs that inherits from UltraGrid.
I added a Property FirstRow in the ctlTaskDataGrid.cs to store the FirstRow and set it later in the forms using the ctlTaskDataGrid control.
Then in the LoadData Method on the Form using the ctlTaskDataGrid.cs control (named ugvShipmentMovements in this case) I do this:
Somewhere the ugvShipmentMovements.DisplayLayout.RowScrollRegions[0].FirstRow was reseted and I can't find where or why. But the most strange behaviour is when I force the ugvShipmentMovements.DisplayLayout.RowScrollRegions[0].FirstRow = ugvShipmentMovements.FirsRow (this is the property I made on the ctlTaskGrid.cs) it doesn't do anything at all:
This is getting very frustrating.. Any help is more than welcome!
First I thought it had something to do with the inheritance somehow, but then why does it works fine with a datarow? It's the exact same way of setting it, only then ugvShipmentMovements.DisplayLayout.RowScrollRegions[0].FirstRow doesn't get resetted.
Well, what I would probably do is avoid resetting the data source, if possible. Whenever the DataSource sends a reset notification to the grid, or when the grid's DataSource property is set, the grid has to throw away everything and start over. So the ideal solution would be to avoid doing those things. I realize, of course, that this is not always possible.
Barring that, I think what you are doing is correct. You would need to store some kind of Key information about the first visible row and then find that row and set it back after the reset occurs.
Where I am getting lost here is in what exactly is not working any why. Other than the fact that a GroupByRow can't use cell values as key information, there's really no difference between a GroupByRow and a regular row. Using the Value and Column as a key should work.
One reason I can think of why this might not work is because the grouping may be done lazily. In which case, when you looped through the grid rows after the reset, you would not be able to find the GroupByRow. I don't think that's the issue here, though, because if it were, it would be immediately obvious to you that your code was simply never finding the GroupByRow that it saved.
Another reason this may not work is because once the grid is grouped, the rows are in a hierarchy. So if the first row in the grid happens to be a child row, then looping through grid.Rows will not find that row. To get around this, you would use one of the methods on the Rows collection that gets all of the childs rows in addition to the parent rows, like GetRowsEnumerator. But once again, if the row were not found at all, this would be immediately obvious to you, so I don't think that's the issue, either.
The only thing I want in fact is to have the same screen after the users click refresh (or an automatic refresh). Refresh = reload the datasource.
If a groupbyrow was the first displayed row, than that groupbyrow should be the first row to display after the refresh. If it's a datarow, then it should be that datarow. I don't think I'm the only one requiring that behaviour. Nothing more frustrating for the user to have to scroll back to where he was before the refresh, after each refresh.
For the groupbyrow, I use the description but I split the string to not include the '( 3 items)' when comparing after the refresh, because indeed, after a refresh it could be different. But I can try working with a Column and Value combination too, that's not the issue I think.
I just need to know how to keep the same row (groupedby or not) on the visible top after a refresh than it was before the refresh. How would you implement that?
You kinda lost me about half way through your post. I was with you up until this:
AndyCaignie said: When the DisplayLayout.RowScrollRegions[0].FirstRow.IsGroupByRow == true. I Store the Row.Description (since groupbyrows don't have Primary Keys) and search for it after DataSource is updated. Strangely enough, The correct row is saved in my FirstRow property! but then when I do: DisplayLayout.RowScrollRegions[0].FirstRow = this.FirstRow
When the DisplayLayout.RowScrollRegions[0].FirstRow.IsGroupByRow == true. I Store the Row.Description (since groupbyrows don't have Primary Keys) and search for it after DataSource is updated. Strangely enough, The correct row is saved in my FirstRow property! but then when I do:
DisplayLayout.RowScrollRegions[0].FirstRow = this.FirstRow
I'm not sure that using the description of the GroupbyRow makes sense here, since the description may change if the number of child rows within the group changes.
You would probably be better off using a combination of the Column and the Value of the GroupByRow. that would be a more generic solution.
But I'm not entirely sure I understand exactly what the problem is as you describe it.
AndyCaignie said:And I was wondering why RowScrollRegions is a collection since DisplayLayout.RowScrollRegions[>0] is always IndexOutOfRange.
To create a new RowScrollRegion, you can call the Split method on an existing scrollregion in code. Or, you can drag the little thumb which is above the vertical scrollbar. This thumb will not be displayed if MaxRowScrollRegions is 1, though.
Hi, I store primary keys of the First row before DataSource is updated and then loop through the rows after datasource is updated to check if for the row with those PK's.
I store this row in a selfmade FirstRow property and in the paint event, if the datasource has been updated (saves this with a boolean), I set the DisplayLayout.RowScrollRegions[0].FirstRow = this.FirstRow.
This works great as long as I don't do a GroupBy with the UltraGrid.
eg:
this.FirstRow.Description = 'Plan Department: BE (16 items)' -> this is the first row before I refreshed
DisplayLayout.RowScrollRegions[0].FirstRow = 'Plan Department (5 items)' - this is the first row of the whole grid
The DisplayLayout.RowScrollRegions[0].FirstRow is still the top first row of the grid(not of the rowscrollregion). So it always scrolls to the top of the grid instead of the location it was before the refresh.
Do you have any idea where it could go wrong? And I was wondering why RowScrollRegions is a collection since DisplayLayout.RowScrollRegions[>0] is always IndexOutOfRange.
Any help would be greatly appreciated!