【问题标题】:DataGridView Custom Sort - How to compare regardless of data type?DataGridView 自定义排序 - 如何比较数据类型?
【发布时间】:2012-07-02 21:37:22
【问题描述】:

我有一个 DataGridView,我需要使用自定义排序器(派生自 System.Collections.IComparer)。那工作得很好,但我注意到我的比较并没有完全正确,因为它最终会对单元格进行字符串比较,而不管它们的底层数据类型如何。 (so, 1, 10, 2) 而不是 (1, 2, 10)。

如何编写一个比较函数来适当地比较列而不考虑它们的数据类型?

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 and cell 2 based on the data type in
    //dr1.Cells["SomeName"].ValueType.
}

【问题讨论】:

    标签: c# .net .net-3.5 datagridview


    【解决方案1】:

    对于这个问题的任何解决方案,似乎都有几个基本部分。

    1. 确保您在比较相似的类型。
    2. 确保您可以比较该类型的实例。

    这里有一些想法可以帮助您入门。为了清楚起见,我省略了一些错误检查。

    假设:

    Type type1 = dr1.Cells["SomeName"].ValueType;
    Type type2 = dr2.Cells["SomeName"].ValueType;
    

    然后看看你是否可以将一个值强制转换为另一个类型:

    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 to string comparison
        {
            cell1 = tc1.ConvertToString(cell1);        
            type1 = cell1.GetType();
    
            cell2 = tc2.ConvertToString(cell2);        
            type2 = cell2.GetType();
        }
        // cell1 and cell2 should be the same type now
    }
    

    既然您有类似类型的实例,您需要找到一种方法来比较它们。

    如果您使用的是 C# 4,那么动态关键字可能是您的朋友:

    dynamic c1 = cell1;
    try 
    {
        int compareResult = c1.CompareTo(cell2);
    }
    catch(Exception)
    {
        // type1 doesn't implement an IComparable-like interface
    }
    

    如果您没有使用 C# 4,您可以查看这些值是否实现了IComparable

    if (cell1 is IComparable)
    {
       int compareResult = ((IComparable)cell1).CompareTo(cell2);
    }
    

    或者它实现了一个通用的IComparable<T>,在这种情况下可能需要使用一些反射技巧:

    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 });
    }
    

    最后,您可以再次使用一些反射来查看Comparer&lt;T&gt;.Default 是否有效:

    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 });
    

    如果这些都不起作用,那么您将不得不回退到字符串比较。

    【讨论】:

      【解决方案2】:

      转换为适当的类型

      Int32 i1 = Int32.Parse(cell1.Tostring());
      
      Int32 i2 = Int32.Parse(cell2.Tostring());
      
      return i1.Compare(i2);
      

      【讨论】:

      • 这仅在单元格中的值可以转换为整数时才有效。如果我理解正确,这些值可能是任意类型。
      • 第一行被转换为适当的类型。 Int32 是一个示例。那么在“SomeName”列中,您不知道该列中的整数类型是什么?如果是这种情况,您怎么知道这两行将是相同的整数类型?我你绝对不知道类型然后转换为字符串。
      • @MonroeThomas 你有一个很好的答案已经给你+1
      猜你喜欢
      • 2017-02-07
      • 1970-01-01
      • 1970-01-01
      • 2011-05-10
      • 2013-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-01
      相关资源
      最近更新 更多