I created a new interface based on IComparer, which allows you to specify both the column and the direction. I just did it because I need my sort code to be as general as possible - I have two lattices that need to be sorted like this, and I don't want to support the code twice. Here is the interface, quite simple:
public interface IByColumnComparer : IComparer { string SortColumn { get; set; } bool SortDescending { get; set; } }
Obviously, if you are not worried about keeping things common (you probably should), then this is not strictly necessary. Then I built a new class based on the BindingList <>. This allowed me to override the sort code and provide my own IByColumnComparer in a column by column, which allowed for the flexibility I needed. Check this:
public class SortableGenericCollection<T> : BindingList<T> { IByColumnComparer GenericComparer = null; public SortableGenericCollection(IByColumnComparer SortingComparer) { GenericComparer = SortingComparer; } protected override bool SupportsSortingCore { get { return true; } } protected override bool IsSortedCore { get { for (int i = 0; i < Items.Count - 1; ++i) { T lhs = Items[i]; T rhs = Items[i + 1]; PropertyDescriptor property = SortPropertyCore; if (property != null) { object lhsValue = lhs == null ? null : property.GetValue(lhs); object rhsValue = rhs == null ? null : property.GetValue(rhs); int result; if (lhsValue == null) { result = -1; } else if (rhsValue == null) { result = 1; } else { result = GenericComparer.Compare(lhs, rhs); } if (result >= 0) { return false; } } } return true; } } private ListSortDirection sortDirection; protected override ListSortDirection SortDirectionCore { get { return sortDirection; } } private PropertyDescriptor sortProperty; protected override PropertyDescriptor SortPropertyCore { get { return sortProperty; } } protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) { sortProperty = prop; sortDirection = direction; GenericComparer.SortColumn = prop.Name; GenericComparer.SortDescending = direction == ListSortDirection.Descending ? true : false; List<T> list = (List<T>)Items; list.Sort(delegate(T lhs, T rhs) { if (sortProperty != null) { object lhsValue = lhs == null ? null : sortProperty.GetValue(lhs); object rhsValue = rhs == null ? null : sortProperty.GetValue(rhs); int result; if (lhsValue == null) { result = -1; } else if (rhsValue == null) { result = 1; } else { result = GenericComparer.Compare(lhs, rhs); } return result; } else { return 0; } }); } protected override void RemoveSortCore() { sortDirection = ListSortDirection.Ascending; sortProperty = null; } }
EDIT . This should provide some information on how to create your own IComparer based on my interface above. The advantage of having your own IComparer based on the interface is that you can sort several columns in one direction and other columns in others (some columns may be rows and some ints, some may have special rules about what happens on top, etc. d.). Here is an example of how your IComparer might work:
public class MyGenericComparer : IByColumnComparer { private string columnToCompare; private bool descending; public string SortColumn { get { return columnToCompare; } set { columnToCompare = value; } } public bool SortDescending { get { return descending; } set { descending = value; } } public MyGenericComparer(string column, bool descend) { columnToCompare = column; descending = descend; } public int Compare(object x, object y) { MyGenericObject firstObj = (MyGenericObject )x; MyGenericObject secondObj = (MyGenericObject )y; if (descending) { MyGenericObject tmp = secondObj ; secondObj = firstObj ; firstObj = tmp; } if (columnToCompare == "StringColumn") {
Then all you have to do is create a list with an instance of your comparator!
public static MyGenericComparer GridComparer = new MyGenericComparer(); public static SortableGenericCollection<GenericObject> GridList = new SortableGenericCollection<GenericObject>(GridComparer);
Chris barlow
source share