I have implemented an IComparer class to use on a column that can contain numbers or strings. I'm assigning the comparer in the constructor of the form that has the grid:
grid.DisplayLayout.Bands[0].Columns["Number"].SortComparer = new InvoiceNumberSort();
The comparer works as expected when tested on an arraylist of values (so I know that's not the problem), but when the columnheader is clicked on the grid it appears to be using the default sorter. The HeadClickAction is set to SortSingle
e.g. the expected order is 1,8921,8923,8931,28000,z3423
but the actual order is 1, 28000,8921,8923,8931,z3423
Is there anything else I need to do to get the sort to work when the user sorts on the header?
It looks like the values are being sorted by textual rules rather than by value. If there is a ValueList assigned to the column, how the ValueList is configured to affect sorting can affect this, although I thought assigning a SortComparer would override that behavior.
One thing you can do is put a breakpoint in the Compare method of your IComparer implementation, and step through the code to see why it is sorting differently than you intended. You can also post a simple sample here if you like and we can take a look.
Thanks for the response.
When I use breakpoints on the comparer I see that the sort happens as soon as it is assigned to the column (rather than when the header is clicked, which is what I expected would happen). The grid column is of type string. The idea is that values that are numeric are sorted numerically, and the rest are sorted alphabetically.
As far as I can tell the comparer seems to be working ok - 1 compared to 28000 returns -1 (1 < 28000), 28000 compared to 8921 returns 1 ( 28000 > 8921)
I've tested this against an arraylist of strings and it sorts as expected.
class InvoiceNumberSort : IComparer { public int Compare(object o1, object o2) { UltraGridCell cell1 = (UltraGridCell)o1; UltraGridCell cell2 = (UltraGridCell)o2; string strValue1 = UltraGridCellExtensions.ValueOrDefault(cell1, string.Empty); string strValue2 = UltraGridCellExtensions.ValueOrDefault(cell2, string.Empty); int nValue1 = 0; int nValue2 = 0; bool value1IsInt = int.TryParse(strValue1, out nValue1); bool value2IsInt = int.TryParse(strValue2, out nValue2); int comparison = 0; if (value1IsInt && value2IsInt) { if (nValue1 > nValue2) { comparison = 1; }else if (nValue1 < nValue2) { comparison = -1; } else { comparison = 0; } } else { comparison = (new CaseInsensitiveComparer()).Compare(strValue1, strValue2); } return (comparison); } }
I tried this in a simple sample and it seems to work for me (using latest 2009.2 source). I attached the project for your reference.
Thanks Brian.
I took a look at your sample and I've found the solution: the constructor of the form is too early to assign the sort comparer. I added it to the Load handler for the form which occurs after construction, and now it seems to work fine.
Thanks!