如何使用 TextBox 过滤 DataGridView

How to filter DataGridView using TextBox

我还没有太多经验。我正在尝试过滤包含输入文本的行。 为了.. 我使用 MailKit 接收传入的消息并将来自它们的数据放入 Grid

public void ShowMessages(ImapClient client)
{
    var inbox = client.Inbox;
    inbox.Open(FolderAccess.ReadOnly);
    var query = SearchQuery.All;                                                                             
    var uids = inbox.Search(query);
    var items = inbox.Fetch(uids, MessageSummaryItems.Full | MessageSummaryItems.BodyStructure).Reverse();
    foreach (var item in items)
    {
       ...                                 
       dataGridMessages.Rows.Add(read, item.Envelope.Subject, item.Envelope.From, item.Envelope.Date, attach, item.Size, false, item.UniqueId);
    }
}

然后我尝试过滤行

private void searchTxb_TextChanged(object sender, EventArgs e)
{
    BindingSource bs = new BindingSource();
    bs.DataSource = dataGridMessages.DataSource;
    bs.Filter = string.Format("Subject LIKE '%{0}%'", searchTxb.Text);
    dataGridMessages.DataSource = bs;
}

但是输入文本后,网格是空的,什么也找不到。 请告诉我我做错了什么?

您的问题是由于您在网格中一次填充一行而直接添加一行引起的。这样,DataSource 属性 没有设置任何值,如果你想过滤你需要逐行循环并删除不需要的行。

或者,您可以使用 BindingList<T>,其中 T 是您在代码中定义的自定义 class,仅包含您希望在网格中显示的属性。定义此 class 后,您可以创建实例以添加到 BindingList 构造函数中使用的列表中

所以假设有一个像这样的class

private class MailItem
{
    public string Subject {get;set;}
    public string From {get;set;}
    public DateTime DateSent {get;set;}
}

还有一个全局变量在你的 type

表单中
List<MailItem> rows = new List<MailItem>();

为简单起见,我只添加了一些属性,但您可以轻松添加其他属性。
现在当你需要填充网格时使用这个

...
rows.Clear();
var items = inbox.Fetch(uids, MessageSummaryItems.Full | MessageSummaryItems.BodyStructure).Reverse()
foreach(var item in items)
{
    rows.Add(new MailItem {
       Subject = item.Envelope.Subject,
       From = item.Envelope.From,
       DateSent = item.Envelope.Date     
    };
}

现在您可以创建 BindingList 并将其设置为网格的数据源

BindingList<MailItem> bs = new BindingList<MailItem>(rows);
dataGridMessages.DataSource = bs;

最后一步是过滤代码。在这里你需要提取你想要使用的行并应用过滤器

BindingList<MailItem> currentFilter = new BindingList<MailItem>(rows);
dataGridMessages.DataSource = currentFilter.Where(x => x.Subject.Contains(searchTxb.Text)).ToList();

请注意,您需要保留通过调用 Fetch 检索到的原始行集,以便您可以在用户更改文本框内容时应用不同的过滤器。因此,MailItem 列表应该为您的表单保持全局

或者您可以再次调用 Fetch,但即使只检索 100 个元素,这种方法似乎也很慢。更好的模型(恕我直言)是实现一个按钮并在单击该按钮时调用过滤器。

(BindingList 需要 使用 System.ComponentModel