Drew's Blog

The Joys of Technology Explored

Re-Selecting The Currently Selected Row After A DataGrid Sort

This is a follow-up to this previous post about sorting a DataGrid. It turns out that the person who originally asked the question about knowing when the sort would occur, wanted to know this for the purpose of re-selecting the currently selected row after the sort. Well, as it turns out this is entirely possible, but it requires some deeper digging into the data-binding aspects of WinForms (which I love btw). ;)

So here's what you'll need to do. First things first, you're going to need to watch for the sort to happen as was detailed in the previous post. Upon detecting the sort about to happen you must record a key value for the currently selected row in a state field (probably in your Form). Now, here's where the deeper knowledge of data-binding comes into play. You must also attach an event listener to the ItemChanged event of the CurrencyManager for the DataTable/DataView you've bound your DataGrid to. The ItemChanged event will fire after the sort takes place at which point you use the DataView's (DataTable::DefaultView if you're bound directly to a DataTable) Find method to locate the row in the view by the key value that you stored in your state field in the sort detection event logic. Once you've found the new position of the row in the DataView after the sort, you set the CurrencyManager's Position property to that index.

Ok, this might sound complex, but lemme show you just how easy it is with some code. For the purposes of keeping this code concise, assume this code is in a Form subclass which contains a DataGrid in a member variable called "myDataGrid". This DataGrid is then bound to a DataTable, stored in a member variable called "myDataTable" which has a key column named "key" of type int:


public class MyForm : Form
{
  private int currentlySelectedRowId = -1;

  public MyForm()
  {
    this.InitializeComponent();

    // Get the CurrencyManager for the bound DataTable
    CurrencyManager dataTableCurrencyManager = (CurrencyManager)this.myDataGrid.BindingContext[this.myDataTable];

    // Hook up to the ItemChanged event
    dataTableCurrencyManager.ItemChanged += new ItemChangeEventHandler(this.myDataTableCurrencyManager_ItemChanged);
  }

 
private void myDataGrid_MouseUp(object sender, MouseEventArgs args)
  {
    DataGrid.HitTestInfo hitTestInfo = this.myDataGrid.HitTest(args.X, args.Y);

    if(hitTestInfo.Type == DataGrid.HitTestType.ColumnHeader)
    {
      // Get the CurrencyManager for the bound DataTable
      CurrencyManager dataTableCurrencyManager = (CurrencyManager)this.myDataGrid.BindingContext[this.myDataTable];

      // Get the current DataRowView
      DataRowView currentRowView = (DataRowView)dataTableCurrencyManager.Current;

      // Remember the currently selected row ID
      this.currentlySelectedRowId = (int)currentRowView["key"];
    }
  }

  private void myDataTableCurrencyManager_ItemChanged(object sender, ItemChangeEventArgs args)
  {
    // Only execute this logic if we're in the state of sorting
    if(this.currentlySelectedRowId != -1)
    {
      // Find the new position of the row now that it's been sorted
      int newPosition = this.myDataTable.DefaultView.Find(this.currentSelectedRowId);

      // Get the CurrencyManager for the bound DataTable
      CurrencyManager dataTableCurrencyManager = (CurrencyManager)this.myDataGrid.BindingContext[this.myDataTable];

      // Change the position of the currency manager
      dataTableCurrencyManager.Position = newPosition;

      // Reset sorting state
      this.currentSelectedRowId = -1;
    }
  } 
}

Posted: Jan 22 2003, 10:14 AM by drub0y | with 10 comment(s)
Filed under:

Comments

Josh King said:

The only part of this code that I don't understand is this part:

\// Remember the currently selected row ID
this.currentlySelectedRowId = (int)currentRowView["key"];

What does "key" mean and how does that get the selected row?

Thanks,
# October 23, 2003 12:12 PM

Drew Marsh said:

"key" is just an example column name that represents the key column in the DataTable. In this example it's an int, but it could just as easliy be a string, guid, etc.

So, if you had a table called "Members" and a unique string column "email", the code would be:

// Remember the currently selected row ID
this.currentlySelectedRowId = (string)currentRowView["email"];

Follow?

HTH,
Drew
# October 23, 2003 12:22 PM

Josh King said:

I do understand the meaning of key. I guess my question is how does it find the current row, just by the name of the key? There could be 20 different rows. How does it know which one you want?

# October 24, 2003 3:59 PM

Drew Marsh said:

The currentRowView is a DataRowView which was retrieved from dataTableCurrencyManager.Current. So it's the key value of that *specific* row.
# October 24, 2003 4:32 PM

Nook said:

Where is "this previous post" (http://radio.weblogs.com/0104813/categories/net/2003/01/22.html#a212) ?? Wrong URL?

[Macro error: Can't compile this script because of a syntax error.]

Thanks
# December 5, 2003 1:46 AM

Drew Marsh said:

Fixed the link. Some of the early entries in this weblog were transferred from my old weblog and I guess I didn't patch all the URLs up.

Thanks,
Drew
# December 5, 2003 10:52 AM

Josh Ross said:

This is stupid. Microsoft's datagrid is broken. If you have a control that is sortable, shouldn't you be able to retreve a CORRECT selected value out of that sorted datagrid without having to jump through hoops of concurency managers?

Can someone post a usercontrol, based upon a datagrid, that works correctly after it has been sorted.
# February 20, 2004 2:08 PM

quamruzzaman said:

Use ultragrid of infragistics

# September 25, 2007 11:45 PM

nil karaibrahimgil said:

Thank you so much..

It's very useful!

King Regards!

# July 18, 2008 2:39 AM

usama said:

os habГ©is equivocado, probable?  

http://eru1.myftp.biz/  

tranlaura

# August 18, 2011 6:27 PM
Leave a Comment

(required) 

(required) 

(optional)

(required)