【问题标题】:Change order of rows in DataTable in C#在 C# 中更改 DataTable 中的行顺序
【发布时间】:2016-07-27 22:26:18
【问题描述】:

是否可以更改 DataTable 中的行顺序,例如当前索引为 5 的行移动到索引为 3 的位置等?

我有这个遗留的、凌乱的代码,下拉菜单从 DataTable 中获取它的值,它从数据库中获取它的值。不可能在数据库中进行更改,因为它有太多的列和条目。我最初的想法是在 db 中添加新列并按其值排序,但这将很难。

因此,由于这只是向用户展示的问题,我想只是切换该 DataTable 中的行顺序。有人知道在 C# 中执行此操作的最佳方法吗?

这是我当前的代码:

    DataTable result = flokkurDao.GetMCCHABAKflokka("MSCODE");

    foreach (DataRow row in result.Rows)
    {
         m_cboReasonCode.Properties.Items.Add(row["FLOKKUR"].ToString().Trim() + " - " + row["SKYRING"]);
    } 

例如,我想将行 2011 - Credit 之前发布到 DataTable 的顶部。

解决方案:

对于那些在 DataTable 中对行进行排序以及使用不支持 Linq 的过时技术时可能遇到问题的人,这可能会有所帮助:

DataRow firstSelectedRow = result.Rows[6];
DataRow firstNewRow = result.NewRow();
firstNewRow.ItemArray = firstSelectedRow.ItemArray; // copy data
result.Rows.Remove(firstSelectedRow);
result.Rows.InsertAt(firstNewRow, 0);

您必须克隆行,将其删除并使用新索引再次插入。此代码将索引为 6 的行移动到 DataTable 中的第一位。

【问题讨论】:

  • 你真的想要随机顺序吗?如果是这样,随机只有一次还是总是不同?既然您想添加一列,是否有您想要用于订购的业务逻辑?
  • @TimSchmelter 嗨,蒂姆,只随机一次。我想一直这样。只是用户希望在该下拉列表的顶部有一些条目。 (用户将是用户)我附上了图片,对我要完成的工作进行了更多解释。
  • @nemo_87 关于您的解决方案:如果要将数据表持久化回数据库,请小心。即使您认为除了订单之外没有更改任何内容,数据适配器也会创建删除和插入查询,如果您有外键约束,这可能会很危险。

标签: c# sorting datatable


【解决方案1】:

如果你真的想要随机性,你可以在 LINQ 的 OrderBy 中使用 Guid.NewGuid

DataTable result = flokkurDao.GetMCCHABAKflokka("MSCODE");
var randomOrder = result.AsEnumerable().OrderBy(r => Guid.NewGuid());
foreach (DataRow row in randomOrder)
{
    // ...
}

如果您实际上不想要随机性,但您想要顶部的特定值,您可以使用:

var orderFlokkur2011 = result.AsEnumerable()
    .OrderBy(r => r.Field<int>("FLOKKUR") == 2011 ? 0 : 1);

【讨论】:

  • 我可能没有解释清楚。将不得不编辑我的问题,我不想要完全随机性,我需要以非常规的方式对它们进行排序,例如:索引为 5 的行始终位于 DataTable 的顶部,索引为 2 的行切换为索引3等。我只需要下一次这个订单,这就是它应该保持的方式......@TimSchmelter
  • 你看到我的第二种方法了吗?
  • 我刚刚做了,当我添加它时,它缺少 DataTable 的 AsEnumerable 和 OrderBy,你可能知道我必须包含哪个命名空间才能获得它们吗?甚至有可能我做不到,因为这是使用 WinForms 的超级旧软件...@TimSchmelter
  • 它是System.Linq,你可以在visual studio 2008/.NET 3.5 中使用它
  • 我已经添加了一个,但它不是,但它仍然未被使用,并且 AsEnumerable 无法识别。 @TimSchmelter
【解决方案2】:

您可以使用 linq 对行进行排序:

DataTable result = flokkurDao.GetMCCHABAKflokka("MSCODE");

foreach (DataRow row in result.Rows.OrderBy(x => x.ColumnName))
{
     m_cboReasonCode.Properties.Items.Add(row["FLOKKUR"].ToString().Trim() + " - " + row["SKYRING"]);
} 

按多列排序:

result.Rows.OrderBy(x => x.ColumnName).ThenBy(x => x.OtherColumnName).ThenBy(x.YetAnotherOne)

按特定值排序:

result.Rows.OrderBy(x => (x.ColumnName == 2001 or x.ColumnName == 2002) ? 0 : 1).ThenBy(x => x.ColumName)

您可以使用上面的代码将某些行“固定”到顶部,如果您想要更精细,可以使用开关,例如将特定值排序为 1、2、3、4 的排序值并使用其余的数字更高。

【讨论】:

  • 不关心问题的“随机”部分
  • @lysp 按列名排序不是问题...但问题是我需要按行进行:(
  • “随机”由答案中的特定值部分解决(第三个代码块)。
【解决方案3】:

你不能在foreach循环中更改顺序或删除一行,你应该创建一个新的数据表并将行随机添加到新的数据表中,你还应该跟踪插入的行不要重复

【讨论】:

    【解决方案4】:

    使用数据视图

    DataTable result = flokkurDao.GetMCCHABAKflokka("MSCODE");
    DateView view = new DateView(result);
    view.Sort = "FLOKKUR";
    view.Filter = "... you can even apply an in memory filter here ..."
    
    foreach (DataRowView row in view.Rows)
    {
        ....
    

    每个数据表都带有一个可以使用的视图DefaultView,这样您就可以在数据层中应用默认的排序/过滤。

    public DataTable GetMCCHABAKflokka(string tableName, string sort, string filter)
    {
        var result = GetMCCHABAKflokka(tableName);
        result.DefaultView.Sort = sort;
        result.DefaultView.Filter = filter;
        return result;
    }    
    
    // use like this
    foreach (DataRowView row in result.DefaultView)
    

    【讨论】:

    • 不要忘记 DataTable 保持不变。只有您的视图被排序。您可以使用 result.DefaultView.ToTable() 将视图转换回 DataTable
    猜你喜欢
    • 2011-04-15
    • 2017-08-23
    • 2011-08-12
    • 1970-01-01
    • 2014-04-10
    • 1970-01-01
    • 2010-11-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多