views:

529

answers:

2

This is a C# Winform question. I have a DataGridView which is bounded to a DataTable. I construct the DataTable myself, which several DataColumn instances. When the DataTable is bound to the DataGridView, by default, every column is sortable by clicking the headers of the DataGridView.

But the sorting behavior is something "by default". It seems that it is sorted by string. This is true even if I put this as my code:

DataColumn dc = new DataColumn("MyObjectColumn", typeof(MyObject));

And MyObject has overriden ToString() and has implemented the IComparable interface. That means even if I have told the DataTable how to sort the special column with the implementation of IComparable interface, DataGridView still doesn't do it the way I expect.

So how can I let DataTable sort data in the way I want?

Thanks for the answers.

A: 

I would recommend using the DefaultView of the DataTable. It has some built in sorting features that are little more extendable. The easiest is RowFilter, but I'm not sure if this will be what you're looking for if your data types are overridden as .ToString() at the table level.

EDIT: added code snippet

A custom method like this that maybe even overrides or is called during the sort event of your DataGridView might be able to sort a DataView before the binding actually occurs. But as I understand it, the IComparable never gets called unless you specify it to be called.

protected void SortGrid()
{
    System.Data.DataView dv = myDataTable.DefaultView;

    myOjbect comparer = new MyObject();

   // Comparer specifics go here. Sort order, column/fieldname etc
   // or any custom properties used in sorting

   dv.Sort(comparer)

   dgMyGrid.DataSource = dv
   dgMyGrid.DataBind()

}
Joel Etherton
Thank you Joel. I know DefaultView gives you some control on sorting. But to my knowledge it is very limited to column and sort order. What on my hand is some more complicated sorting such as sorting according to numeric values rather than literal values of the converted strings.Filtering is out of question here to my view. I do not want to filter any row, just reordering them in the way I want.Any further suggestion or hints?
Steve
Well, if you've already implemented IComparable and that's not working I really could only suggest 2 things: figure out why it's not working or go low-fi. Low-fi: write a static method that reconstructs the table row by row in the sort order you want based on MyObject (undesirable). Is the sort out of order in any rational manner? Is it possible that your IComparable isn't performing as you expect it? Or is it possible that your IComparable is never being reached?
Joel Etherton
Joel: of course the IComparable method is never reached, otherwise it wouldn't be a problem. What confuses me is that even if the DataColumn knows the type of data bound to it and the type implements IComparable, when sorting from grid, .net doesn't seem to use the IComparable to sort the data. How is sorting done? How can I customize the behavior?
Steve
Well as I've read IComparer (and I don't have much experience with it), you need to call the sort feature explicitly. The default sort() call that is used won't ever access it. I'm using EDIT above to throw in a code snippet "shot in the dark".
Joel Etherton
Joel: I found out why sorting DataTable doesn't fire up my IComparable method. It is because I implement the IComparable<T> interface. If class A implements IComparable<A> template interface, "obj of A is IComparable" will return false and the "default" comparison behavior will then compare the string format of two objects of A, rather than using the CompareTo method from template interface.To solve my problem, I just change the interface of my class from IComparable<T> to IComparable.
Steve
@Steve: That's good to know. I envision IComparable on some of my classes in the near future.
Joel Etherton
A: 

I had to deal with this today. I've implemented a natural sort (hat tip: http://stackoverflow.com/questions/248603/natural-sort-order-in-c) and had to sort a DataTable. This is more of a "low fi" method, but it did the trick for the small dataset I'm working with.

I'm creating a key/value value relationship between my sorting column, and the DataRow itself, and popping it into a SortedList constructed with an IComparer.

DataTable myDataTable = {all my data...}
SortedList myDataNaturallySorted = new SortedList(new NaturalComparer());

foreach (DataRow dataRow in myDataTable.AsEnumerable())
    myDataNaturallySorted.Add(dataRow["columWithKeyName"].ToString(), dataRow);

Then I moved forward using the sorted list as a data source for my repeater.

Joisey Mike