在C#中改变DataTable中行的顺序

6

有没有可能在DataTable中更改行的顺序,例如将当前索引为5的行移动到索引为3的位置等?

我有一个混乱的旧代码,其中下拉菜单从DataTable获取其值,DataTable从数据库获取其值。由于数据库具有太多的列和条目,因此无法对其进行更改。我的原始想法是在数据库中添加新列并按其值排序,但这将很困难。

因此,既然这只是向用户呈现的问题,我考虑只需在该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推到DataTable的顶部。

enter image description here

解决方案:

对于那些在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 的第一位。

你真的想要随机顺序吗?如果是这样,是只需要一次随机还是每次都不同?既然你想添加一列,那么你是否有一个业务逻辑来用于排序? - Tim Schmelter
@TimSchmelter 你好,随机只有一次。我希望它一直保持这样。用户只是想在下拉列表的顶部有一些条目。我附上了一张图片,更详细地解释了我想要实现的内容。 - nemo_87
这可能会对你有所帮助:https://dev59.com/U1zUa4cB1Zd3GeqP2FJA - sujith karivelil
1
关于你的解决方案:如果你想将数据表格持久化到数据库,请小心。即使你认为除了顺序之外没有改变任何内容,一个数据适配器也会创建一个删除和插入查询,如果你有外键约束,这可能是危险的。 - Jürgen Steinblock
4个回答

1
您可以使用 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并对其余值使用较高数字。

1
不关心问题中的“random”部分。 - Tim Schmelter
@lysp 按列名排序并不是问题... 但问题是我需要按行排序 :( - nemo_87
“Random”在答案的特定值部分中被提及(第三个代码块)。 - lysp

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 - nemo_87
你看到我的第二种方法了吗? - Tim Schmelter
刚刚我添加了它,发现 DataTable 缺少 AsEnumerable 和 OrderBy 方法。你知道我需要引用哪个命名空间才能获取这些方法吗?不过可能无法做到,因为这是使用 WinForms 的非常老的软件... @TimSchmelter - nemo_87
它是System.Linq,您可以在Visual Studio 2008/.NET 3.5中使用它。 - Tim Schmelter
我立即添加了它,但它仍然未被使用,而且AsEnumerable未被识别。@TimSchmelter - nemo_87

0
使用DataView。
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。 - CathalMF

0

在foreach循环中,您无法更改顺序或删除行,应创建一个新的数据表并随机将行添加到新的数据表中,还应跟踪插入的行以避免重复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接