如何使用 DataTable.DefaultView.RowFilter 筛选项目

How to filter items with DataTable.DefaultView.RowFilter

提问人:Arie 提问时间:3/22/2023 最后编辑:JimiArie 更新时间:10/15/2023 访问量:267

问:

我的项目中绑定了 .我希望能够仅将项目筛选为与我在其他控件中键入的文本匹配的项目。我知道我可能会在我的旧 vb.net 项目中使用如下所示的以下属性。然而,当我尝试在我最近的 Visual Studio C# 项目中做同样的事情时,似乎不再被认可。如果这是不合时宜的,或者有任何其他方法,我该如何过滤项目?listboxdatasourcetextboxDefaultView.RowFilterDefaultView

listbox1.DataSource.DefaultView.RowFilter = "[Nummer] like '%" & lbSearchProd.Text.Trim()

编辑 @dr.null

我添加了以下行,但是我收到以下错误。请注意,数据源包含项。

(cbClient.DataSource as DataTable).DefaultView.RowFilter = "[Value] like '%" + txtFilterClient.Text.Trim() + "%'";

enter image description here

这是我绑定控件的方式:

public void LoadDataToClients(IEnumerable<IdValueReadModel> clients)
{
    cbClient.DataSource = clients.ToList();
    cbClient.DisplayMember = "Value";
    cbClient.ValueMember = "Id";
}

数据在那里:

enter image description here

C# vb.net WinForms DataTable RowFilter

评论

0赞 dr.null 3/22/2023
在 c# 中不允许编写此代码。在旧的 vb.net 项目中关闭该选项首先是一个错误。在 c# 中,必须将对象强制转换为指定的类型。如果它像你的代码片段所建议的那样,那么你需要写:.Option Strict Off.DataSourceDataTable(listbox1.DataSource as DataTable).DefaultView.RowFilter = ...
0赞 jmcilhinney 3/22/2023
正如建议的那样,您应该首先在 VB 应用程序中安装,然后您将在那里做正确的事情,而不必在这里做任何事情。也就是说,在 C# 和 VB 中,您确实应该使用 a。 将 a 添加到表单中,将 绑定到 that 和 ,然后您可以设置 .Option Strict OnBindingSourceBindingSourceDataTableListBoxFilterBindingSource
0赞 Arie 3/22/2023
@dr.null,我做到了,但是在执行我得到的代码时我没有看到任何错误: 你可以查看我的主要帖子,我已经添加了屏幕截图。数据源包含项。现在有什么问题?System.NullReferenceException: 'Object reference not set to an instance of an object.' (... as System.Data.DataTable) returned null.
0赞 dr.null 3/22/2023
数据源的类型是什么? ? ?还?在调用此代码之前,您是否绑定了?DataTableDataView.DataSource
0赞 Arie 3/22/2023
@dr.null 是的,我在使用您的代码之前通过调用来绑定控制,并且控制中已经有数据 - 请参阅我粘贴代码的主要帖子。LoadDataToClients()

答:

3赞 dr.null 3/23/2023 #1

澄清对上述问题的评论。

首先

listbox1.DataSource.DefaultView.RowFilter = "[Nummer] like '%" & lbSearchProd.Text.Trim()

此行在旧的 vb.net 项目中有效,因为您具有 Option Strict Off,它允许隐式缩小转换、后期绑定和导致类型的隐式类型化。如果你想写出好的 vb.net 代码,并通过这样做来避免可能的错误和错误,你就不应该允许上述内容。在 c# 中,没有该选项。您需要将 强制转换为分配的对象实例的类型才能访问它。objectobject

其次,你这里的数据源是一个 not .它们是两个不同的东西,你不能将可以为一个写的东西应用到另一个。您需要过滤 .List<T>DataTableLinqList<T>

一些建议的解决方案。


DataTable
从数据访问中获取 a。像这样:
DataTable

// SqlClient example...
private DataTable GetDataTable()
{
    var dt = new DataTable();

    using (var con = new SqlConnection("...."))
    using (var cmd = new SqlCommand("Select...", con))
    using (var da = new SqlDataAdapter(cmd))
    {
        con.Open();
        da.Fill(dt);
    }

    return dt;
}

绑定它:

private void LoadClient()
{
    cbClient.DisplayMember = "Value";
    cbClient.ValueMember = "Id";
    cbClient.DataSource = GetDataTable();
}

处理过滤器或移除过滤器:TextBox.TextChanged

private void txtFilterClient_TextChanged(object sender, EventArgs e)
{
    if (cbClient.DataSource is DataTable dt)
    {
        var str = txtFilterClient.Text.Trim();

        dt.DefaultView.RowFilter = string.IsNullOrEmpty(str)
            ? null
            : $"Value LIKE '%{str}%'";
    }
}


BindingSource 与第一个解决方案一样,获取 but 将控件绑定到多用途 BindingSource
DataTable

private void LoadClient()
{
    cbClient.DisplayMember = "Value";
    cbClient.ValueMember = "Id";
    cbClient.DataSource = new BindingSource(GetDataTable(), null);
}

private void txtFilterClient_TextChanged(object sender, EventArgs e)
{
    if (cbClient.DataSource is BindingSource bs)
    {
        var str = txtFilterClient.Text.Trim();

        bs.Filter = string.IsNullOrEmpty(str)
            ? null
            : $"Value LIKE '%{str}%'";
    }
}


List<T>
如果你需要操作一个,并且你有一个模型,比如:
List<T>

public class IdValueReadModel
{
    public int Id { get; set; }
    public string Value { get; set; }
}

然后,您可以执行查询来过滤其类型的数据源。清除筛选器时,需要将原始列表缓存在类字段中作为数据源。运行查询以绑定新的筛选列表。LinqList<IdValueReadModel>Linq

private List<IdValueReadModel> clientCache;

private void LoadClient()
{
    clientCache = // Get/assign the list...
    cbClient.DisplayMember = "Value";
    cbClient.ValueMember = "Id";
    cbClient.DataSource = clientCache;
}

private void txtFilterClient_TextChanged(object sender, EventArgs e)
{
    var str = txtFilterClient.Text.Trim().ToLower();

    cbClient.DataSource = string.IsNullOrEmpty(str)
        ? clientCache
        : clientCache
        .Where(c => c.Value.ToLower().Contains(str))
        .ToList();
}

评论

0赞 Arie 3/23/2023
在您的 RowFilter 中,如果过滤器文本为空,这究竟意味着什么:?? null
2赞 dr.null 3/23/2023
如果搜索词为空,则使用三元条件运算符来设置或删除筛选器。就像:.vb.net 等效项是 。如果没有要搜索的单词,您希望删除过滤器。不是吗?if (string.IsNullOrEmpty(str)) //clear the filter else //set the filter;.RowFilter = If(string.IsNullOrEmpty(str), Nothing, $"Value LIKE '%{str}%'")
0赞 Arie 3/24/2023
但事实并非如此;t clean datasource 本身,这意味着 datasource 保持原样,但如果没有匹配的单词,控件的项目将显示为空列表?
0赞 dr.null 3/25/2023
@Arie正确。源数据将保持设置/删除过滤器时的状态。