c# - DataGridView Custom Sort - How to compare regardless of data type? -


i have datagridview , need use custom sorter (derived system.collections.icomparer). working fine, noticed hadn't quite gotten comparisons right because ends doing string compare on cells regardless of underlying data type. (so, 1, 10, 2) instead of (1, 2, 10).

how can write compare function appropriately compare columns regardless of data type?

public int compare(object x, object y) {     datagridviewrow dr1 = (datagridviewrow)x;     datagridviewrow dr2 = (datagridviewrow)y;      object cell1 = dr1.cells["somename"].value;     object cell2 = dr2.cells["somename"].value;      //compare cell1 , cell 2 based on data type in     //dr1.cells["somename"].valuetype. } 

it seems there couple of essential parts solution problem.

  1. ensure comparing types.
  2. ensure can compare instances of type.

here ideas started. i've omitted error checking in interest of clarity.

assume:

type type1 = dr1.cells["somename"].valuetype; type type2 = dr2.cells["somename"].valuetype; 

then see if can coerce 1 value other's type:

if (type1 != type2) {     typeconverter tc1 = typedescriptor.getconverter(type1);     typeconverter tc2 = typedescriptor.getconverter(type2);      if (tc1.canconvertfrom(type2))     {         cell2 = tc1.convertfrom(cell2);         type2 = type1;     }     else if (tc1.canconvertto(type2))     {          cell1 = tc1.convertto(cell1, type2);         type1 = type2;     }     else if (tc2.canconvertfrom(type1))     {         cell1 = tc2.convertfrom(cell1);         type1 = type2;     }     else if (tc2.canconvertto(type1))     {          cell2 = tc2.convertto(cell2, type1);         type2 = type1;     }     else // fallback string comparison     {         cell1 = tc1.converttostring(cell1);                 type1 = cell1.gettype();          cell2 = tc2.converttostring(cell2);                 type2 = cell2.gettype();     }     // cell1 , cell2 should same type } 

now have instances of type, need find way compare them.

if using c# 4, dynamic keyword may friend:

dynamic c1 = cell1; try  {     int compareresult = c1.compareto(cell2); } catch(exception) {     // type1 doesn't implement icomparable-like interface } 

if aren't using c# 4, can see if values implement icomparable:

if (cell1 icomparable) {    int compareresult = ((icomparable)cell1).compareto(cell2); } 

or perhaps implements generic icomparable<t>, in case may need resort reflection trickery:

type genericcomparabletype = typeof(icomparable<>); type typedcomparabletype = genericcomparabletype.makegenerictype(new type[] { type1 }); if (typedcomparabletype.isinstanceoftype(cell1)) {     methodinfo compareto = typedcomparabletype.getmethod("compareto", new type[] { type1 });     int compareresult = (int)compareto.invoke(cell1, new object[] { cell2 }); } 

finally, can see if comparer<t>.default work, again using reflection:

type genericcomparertype = typeof(comparer<>); type typedcomparertype = genericcomparertype.makegenerictype(new type[] { type1 }); propertyinfo defaultproperty = typedcomparertype.getproperty("default", bindingflags.static | bindingflags.public);  object defaultcomparer = defaultproperty.getvalue(null, null); methodinfo compare = defaultcomparer.gettype().getmethod("compare", new type[] { type1, type1 }); int compareresult = (int)compare.invoke(defaultcomparer, new object[] { cell1, cell2 }); 

if none of these work, have fallback string comparison.


Comments

Popular posts from this blog

c# - SVN Error : "svnadmin: E205000: Too many arguments" -

c# - Copy ObservableCollection to another ObservableCollection -

All overlapping substrings matching a java regex -