0

I'm designing a new winform application in C# but I having trouble finding the best solution for a specific part of it.

The main part of the app displays 20 rows x 10 columns of data in a grid that it reads every second from an XML, which it does in on a background thread.

The issue I have is with displaying the data. I have a DataSet that receives the data every second and I set this as the data source for my DataGridView which I then update to reflect the changes on screen.

It's quite quick and I don't see the repainting on screen but if I click and highlight a cell, when the update triggers, the focus of my cell jumps back to the top left cell.

Is there anything I can do to stop this from happening whilst maintaining the updating every second?

Also - is the DatGridView the best control for my needs or should I consider another control (or even building a custom control?) If so - what would you recommend?

horgh
  • 17,918
  • 22
  • 68
  • 123
Jimbo James
  • 727
  • 2
  • 9
  • 17
  • So, you should remember the focused row and cell, if any, and put the focus back after the data update has been applied... – horgh Dec 16 '13 at 23:53
  • Yes that's a good idea, I can see that would work. Do you think that a DataGridView is overkill for simply displaying 20 rows of data? I'm ideally looking for speed over functionality. – Jimbo James Dec 16 '13 at 23:55
  • What makes you think it's an overkill? – horgh Dec 16 '13 at 23:57
  • It's my understanding that there is going to be lot of functionality that I don't need or want to use so I guess I am assuming that these extra features will just add bloat? – Jimbo James Dec 17 '13 at 00:10
  • It's not that heavy-weight, if you use it properly, at all – horgh Dec 17 '13 at 00:13
  • Ok - other than the double buffer suggestion you kindly posted below, what other guidelines should I follow to use it properly? – Jimbo James Dec 17 '13 at 00:19
  • Read MSDN: [DataGridView Control (Windows Forms)](http://msdn.microsoft.com/en-us/library/e0ywh3cz%28v=vs.110%29.aspx) – horgh Dec 17 '13 at 00:26

1 Answers1

0

You should remember the key value identifying the selected row. Then after the update has been done, find the index of the row with the key value; scroll to it, if it's not visible after the update and select the cell.

So it would look approximately like this:

int colIndex = gridView.CurrentCell.ColumnIndex; //remember the selected column
var rowId = ...; // remember the Id of the selected row

//...update 

int rowIndex = ...; //find the index of the row by Id in the dataset
var rowToSelect = gridView.Rows[rowIndex]; //get the row in the grid by index
if (!rowToSelect.Displayed) //if this row is not visible on screen
    gridView.FirstDisplayedScrollingRowIndex = rowToSelect.Index; //scroll to it
gridView.CurrentCell = rowToSelect.Cells[colIndex]; //select the cell

Also remember if your grid uses sorting, indeces in the grid may differ from indeces in the dataset, then you'll have to search for the necessary row in the grid differently. For example:

DataGridViewRow rowToSelect= gView.Rows
                     .OfType<DataGridViewRow>()
                     .FirstOrDefault(r => r.Cells[colIndex].Value.Equals(rowId));

Also you may find usefull using double buffering. See SO: How to double buffer .NET controls on a form?. Though I usually inherit from gridView for that:

public class MyDataGridView : DataGridView
{
    public MyDataGridView()
    {
        DoubleBuffered = true;
    }
}
Community
  • 1
  • 1
horgh
  • 17,918
  • 22
  • 68
  • 123
  • `if (!rowToSelect.Displayed) //if this row is not visible on screen gridView.FirstDisplayedScrollingRowIndex = rowToSelect.Index;` - wont work on rows that are not visible and will throw an exception – Boris Kleynbok Oct 29 '15 at 18:24