【问题标题】:Is there a way to filter and limit rows in a DataGridView?有没有办法过滤和限制 DataGridView 中的行?
【发布时间】:2019-10-11 09:00:31
【问题描述】:

我正在编写一个销售程序,为此我需要一个浏览窗口,用户可以在其中浏览他要出售的所有产品。这可能意味着成千上万的产品,因此过滤是唯一的方法。我发现最快的过滤方法是用产品填充 DataTable(而不是直接填充 DataGridView,这是我的第一个解决方案)并使用它的过滤功能。

private void nameTB_TextChanged(object sender, EventArgs e)
{
    browseDataTable.DefaultView.RowFilter = "name LIKE '%" + nameTB.Text + "%'";
}

这完成了仅可视化销售人员(从现在开始:用户)正在寻找的内容的工作,并且它完美地适用于大约 300 行(产品)。 将其增加到 10000 种产品(这不仅仅是为了从商店测试其当前数据库)并且加载时间从 1 秒成倍增长到 40 秒,这在销售环境中是不可接受的。

产品在后台的 MySQL 数据库中。查询并将其保存到 DataTable 需要不到一秒钟的时间,这对于 10000 个产品是可以接受的,当我尝试将其可视化时问题就来了。一个简单的:

datagridview1.DataSource = browseDataTable;

大约需要 4 秒,这是可以接受的,但是对于这个应用程序,我需要在我的 6 列 + 标题中添加样式(所有列都有不同的字体,有些换行,有些没有,等等)这增加了加载时间约为 40 秒,但没有样式,在光线充足的房间中质量较低的触摸显示器上,用户将无法看到行。 限制它是要走的路,我没有找到更好的解决方案然后使用这样的东西

browseDataTable.AsEnumerable().Take(100).CopyToDataTable(visibleDataTable, LoadOption.OverwriteChanges);
datagridview1.DataSource = visibleDataTable;

这使得它再次可视化 1 秒。

我的问题是当我尝试将限制与过滤后的产品一起使用时(仅可视化过滤后的前 100 行)。 尝试组合哪个 DataTable 应该是 DataGridView 的 DataSource,例如这个:

browseDataTable.AsEnumerable().Take(100).CopyToDataTable(visibleDataTable, LoadOption.OverwriteChanges); //done once somewhere

    private void nameTB_TextChanged(object sender, EventArgs e)
    {
        if(nameTB.Text == "")
            datagridview1.DataSource = visibleDataTable;
        else
        {
            browseDataTable.DefaultView.RowFilter = "name LIKE '%" + nameTB.Text + "%'";
            datagridview1.DataSource = browseDataTable;   
        }
    }

没有用,因为通常还有太多产品,最多 3 个字母,每个字母后有 5 秒延迟,3-4 个字母后,它是瞬时的。

理想的解决方案是这样的:

private void nameTB_TextChanged(object sender, EventArgs e)
{
    browseDataTable.DefaultView.RowFilter = "name LIKE '%" + nameTB.Text + "%'";
    browseDataTable.AsEnumerable().Take(100).CopyToDataTable(visibleDataTable, LoadOption.OverwriteChanges);
}

但这也不起作用,因为 'Take(100)' 总是从 DataTable 中取出前 100 个,无论是否过滤。

(限制查询本身也不起作用,因为这样会在每个字母处都有一个查询,这对于联网的服务器会增加网络拥塞并且速度会很慢,特别是如果用户开始快速书写)

【问题讨论】:

  • 如果你得到的值小于这个值,Take 不会报错。所以尝试一个像 10000 这样的数字,它会在 5 秒内返回结果。
  • 我的问题不在于 Take 不够,我可以这样做,但是它会和原版一样慢,因为它是原版的精确副本,所以事实上我可以直接使用原版。
  • 只有当你的数量少于拍摄数量时才会变慢。
  • 所以你要我取10000复制到一个新的DataTable,然后过滤新的DataTable?
  • 这是一种方式。您可以使用 RowFilter 中的 Count 属性,这可能更快 Count(*) docs.microsoft.com/en-us/dotnet/api/…

标签: c# filter datagridview datatable limit


【解决方案1】:

原来答案比我想象的要简单

private void nameTB_TextChanged(object sender, EventArgs e)
{
    browseDataTable.DefaultView.RowFilter = "name LIKE '%" + nameTB.Text + "%'";
    visibleDataTable = browseDataTable.DefaultView.ToTable().AsEnumerable().Take(100).CopyToDataTable();
    datagridview1.DataSource = visibleDataTable;
}

这会过滤到我想要的字母,并将行数限制为 100,这使得整个过程瞬间完成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多