14

我有一个从数据集构建的报告。数据集使用 Sort 属性对数据进行排序。我知道我可以创建这样的排序表达式:

“字段描述,字段 2 递增”

但我现在需要的是一种进行自定义排序的方法。在 SQL 中,我可以通过执行以下操作来执行自定义排序:

order by 
    case when field = 'Some Value' then 0 end
    case when field = 'Another Value' then 1 end

基本上重新定义我的排序(即,一些值出现在另一个值之前)。

是否可以对 DataView 执行类似于排序表达式的操作?

4

5 回答 5

17

好的,我只是快速完成了这个,并没有做所有必要的错误处理和空值检查,但它应该给你一个想法,应该足以让你开始:

public static class DataTableExtensions
{
    public static DataView ApplySort(this DataTable table, Comparison<DataRow> comparison)
    {

        DataTable clone = table.Clone();
        List<DataRow> rows = new List<DataRow>();
        foreach (DataRow row in table.Rows)
        {
            rows.Add(row);    
        }

        rows.Sort(comparison);

        foreach (DataRow row in rows)
        {
            clone.Rows.Add(row.ItemArray);
        }

        return clone.DefaultView;
    }


}

用法:

    DataTable table = new DataTable();
    table.Columns.Add("IntValue", typeof(int));
    table.Columns.Add("StringValue");

    table.Rows.Add(11, "Eleven");
    table.Rows.Add(14, "Fourteen");
    table.Rows.Add(10, "Ten");
    table.Rows.Add(12, "Twelve");
    table.Rows.Add(13, "Thirteen");

//按字符串值排序:

 DataView sorted = table.ApplySort((r, r2) =>
        {
            return ((string)r["StringValue"]).CompareTo(((string)r2["StringValue"]));
        });

结果:

11 十一

14 十四

10 十

13 十三

12 十二

//按 IntValue 排序:

DataView sorted = table.ApplySort((r, r2) =>
            {
                return ((int)r["IntValue"]).CompareTo(((int)r2["IntValue"]));
            });

结果:

10 十

11 十一

13 十三

12 十二

14 十四

编辑:将其更改为扩展方法。

现在在您的 Lambda 中(或者您可以创建一个完整的比较方法),您可以执行您需要的任何类型的自定义排序逻辑。请记住,-1 小于,0 等于,1 大于。

于 2009-02-24T16:43:30.453 回答
17

我喜欢 BFree 的回答,尽管我担心我的代码最终会更新克隆表而不是真实表的风险。(如果您仅在DataView.

DataTable您可以通过向其添加计算值DataColumn(使用Expression属性)然后对其值进行排序来对原始对象执行此操作。

在您的情况下,它将类似于:

DataColumn c = myTable.Columns.Add("Sort", typeof(int));
c.Expression = "iif(field='SomeValue', 0, iif(field='AnotherValue', 1, 2))";

排序SomeValue第一,AnotherValue第二,以及之后的所有其他内容。

于 2009-02-24T22:39:09.977 回答
5

我知道这篇文章有点老,但我通过实现 IComparable 来解决这个问题。在此示例中,我想按版本排序(格式为 0.0.0.0 作为字符串)。

这是实现 IComparable 的版本控制类:

public class Versioning : IComparable {
    string _version;

    int _major;
    public int Major { 
        get { return (_major); } 
        set { _major = value; } 
    }

    int _minor;
    public int Minor {
        get { return (_minor); }
        set { _minor = value; }
    }

    int _beta;
    public int Beta {
        get { return (_beta); }
        set { _beta = value; }
    }

    int _alpha;
    public int Alpha {
        get { return (_alpha); }
        set { _alpha = value; }
    }

    public Versioning(string version) {
        _version = version;

        var splitVersion = SplitVersion();
        if (splitVersion.Length < 4) {
            Major = Minor = Beta = Alpha = 0;
        }

        if (!int.TryParse(splitVersion[0], out _major)) _major = 0;
        if (!int.TryParse(splitVersion[1], out _minor)) _minor = 0;
        if (!int.TryParse(splitVersion[2], out _beta)) _beta = 0;
        if (!int.TryParse(splitVersion[3], out _alpha)) _alpha = 0;
    }

    string[] SplitVersion() {
        return (_version.Split('.'));
    }

    int GetCompareTo(Versioning versioning) {
        var greater = -1;
        var equal = 0;
        var less = 1;

        if (Major > versioning.Major) return (greater);
        if (Major < versioning.Major) return (less);
        if (Minor > versioning.Minor) return (greater);
        if (Minor < versioning.Minor) return (less);
        if (Beta > versioning.Beta) return (greater);
        if (Beta < versioning.Beta) return (less);
        if (Alpha > versioning.Alpha) return (greater);
        if (Alpha < versioning.Alpha) return (less);

        return (equal);
    }

    public int CompareTo(Versioning versioning) {
        return (GetCompareTo(versioning));
    }

    public override string ToString() {
        return (_version);
    }

    public int CompareTo(object obj) {
        if (obj == null) return (1);
        return (GetCompareTo((Versioning)obj));
    }
}

当您将列添加到表中时,不是将 Version 添加为字符串,而是将其添加为 Versioning 类:

_table.Columns.Add("Version", typeof(Versioning));
_view = new View(_table);

然后正常排序:

_view.Sort = "Version";
于 2012-05-11T15:14:31.823 回答
1

我不这么认为。但是,您可以更改 SQL 以返回作为 case 语句结果的“CustomSort”列:

select
    (case when f = 'a' then 0 else 1 end) as CustomSort
from MyTable
于 2009-02-24T16:14:04.393 回答
1

您可以使用 if 或 switch 语句来获得与 select case 语句类似的功能:

            if (Something == "1")
                MyView.Sort = "Field1 ASC";
            else
                MyView.Sort = "Field2 ASC";

或者

            switch (MyProperty)
            {
                case 1:
                    MyView.Sort = "Field1 ASC";
                    break;
                case 2:
                    MyView.Sort = "Field2 ASC";
                    break;
                default:
                    MyView.Sort = "Field3 ASC";
                    break;
            }
于 2009-02-24T16:14:09.683 回答