tags:

views:

469

answers:

1

Hi all,

I'm trying to sort the columns of a datagrid A to Z, the code below works apart from I get a column beginning with 'c' in between the 'A' (e.g. a,a,a,a,c,a,a,b,b,b), this happens the first time I run the code. If I then use columnNames.Reverse(); (Z to A) and then re-run columnNames.Sort() (A to Z) it sorts correctly. Why would this be?

 List<string> columnNames = new List<string>();
 foreach (DataGridViewColumn col in dataGridView1.Columns)
 columnNames.Add(col.HeaderText);
 columnNames.Sort();
 foreach (DataGridViewColumn col in dataGridView1.Columns)
     col.DisplayIndex = columnNames.IndexOf(col.HeaderText);

Thanks

+1  A: 

In your example ("(a,a,a,a,c,a,a,b,b,b)"), the column names are not unique. So in the sorted list of names, the (first) index of "a" will be 0, the (first) index of "b" will be 5, and the (first) index of "c" will be 8.

So as you loop through the columns, you will repeatedly be setting columns with the text "a" to have index "0". The second time you do this, the first column in that position will get moved over to make room. The result is more like shuffling cards than sorting, and the final order depends on the original order. This is why the sort works fine the second time -- during your first pass, you arrange the elements "close enough" that the second attempt succeeds.

What about something like the following instead? It will assign the indices uniquely, and it will also be more efficient. (Each call to IndexOf is O(N), so your original code is O(N^2) -- this is just O(N log N), at least assuming the column collection doesn't rearrange too much as you set indices.)

List<DataGridViewColumn> columns = new List<DataGridViewColumn>(dataGridView1.Columns);
columns.Sort( delegate(DataGridViewColumn a, DataGridViewColumn b) {
               return String.Compare( a.HeaderText, b.HeaderText ); }
int n = 0;
foreach( DataGridViewColumn col in columns )
   col.DisplayIndex = n++;
Eric