You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用TextBox过滤DataGridView中MailKit加载的邮件数据

问题原因
  • 核心问题:你填充DataGridView时直接调用dataGridMessages.Rows.Add()方法插入行,没有为控件绑定DataSource,所以读取dataGridMessages.DataSource返回值为null,将空值赋值给BindingSource后自然没有数据可以过滤展示。
  • 次要问题:每次TextChanged事件触发时都新建BindingSource实例,属于不必要的重复操作,也容易出现上下文数据不一致的问题。
修复方案

方案一:使用DataTable作为绑定数据源(推荐,性能更优)

该方案修改原有填充逻辑,用标准数据绑定实现过滤,适合数据量较大的场景。

  1. 首先在窗体类中声明全局的DataTable和BindingSource对象:
// 全局变量定义,放在窗体类内部
private DataTable _mailDataTable;
private BindingSource _mailBindingSource;
  1. 修改ShowMessages方法的填充逻辑:
public void ShowMessages(ImapClient client)
{
    // 初始化DataTable,列结构和你之前插入行的字段一一对应
    _mailDataTable = new DataTable();
    _mailDataTable.Columns.AddRange(new DataColumn[]
    {
        new DataColumn("Read", typeof(bool)),
        new DataColumn("Subject", typeof(string)),
        new DataColumn("From", typeof(string)),
        new DataColumn("Date", typeof(DateTimeOffset)),
        new DataColumn("HasAttachment", typeof(bool)),
        new DataColumn("Size", typeof(long)),
        new DataColumn("IsSelected", typeof(bool)),
        new DataColumn("UniqueId", typeof(uint))
    });

    var inbox = client.Inbox;
    inbox.Open(FolderAccess.ReadOnly);
    var uids = inbox.Search(SearchQuery.All);
    var items = inbox.Fetch(uids, MessageSummaryItems.Full | MessageSummaryItems.BodyStructure).Reverse();
    
    foreach (var item in items)
    {
        // 按列顺序插入行数据,替换原有直接给DataGridView加行的逻辑
        _mailDataTable.Rows.Add(
            read, 
            item.Envelope.Subject, 
            item.Envelope.From.ToString(), 
            item.Envelope.Date, 
            attach, 
            item.Size, 
            false, 
            item.UniqueId.Id
        );
    }

    // 绑定数据源到DataGridView
    _mailBindingSource = new BindingSource();
    _mailBindingSource.DataSource = _mailDataTable;
    dataGridMessages.DataSource = _mailBindingSource;
}
  1. 修改TextChanged事件的过滤逻辑:
private void searchTxb_TextChanged(object sender, EventArgs e)
{
    if (_mailBindingSource == null) return;
    
    if (string.IsNullOrWhiteSpace(searchTxb.Text))
    {
        // 搜索框为空时清除过滤
        _mailBindingSource.RemoveFilter();
        return;
    }
    
    // 转义输入内容里的单引号,避免语法报错
    var safeSearchText = searchTxb.Text.Replace("'", "''");
    _mailBindingSource.Filter = $"Subject LIKE '%{safeSearchText}%'";
}

方案二:直接控制行可见性(适合小数据量场景)

如果不想修改原有填充逻辑,可以直接遍历DataGridView行,匹配搜索内容后设置行的可见性,数据量超过1000条时不推荐使用。
直接替换TextChanged事件代码即可:

private void searchTxb_TextChanged(object sender, EventArgs e)
{
    var searchText = searchTxb.Text.Trim();
    foreach (DataGridViewRow row in dataGridMessages.Rows)
    {
        // 跳过默认的新行模板
        if (row.IsNewRow) continue;
        
        // 第2列是主题列,对应索引为1,和你之前插入行的顺序一致
        var subject = row.Cells[1].Value?.ToString() ?? string.Empty;
        row.Visible = string.IsNullOrEmpty(searchText) 
                      || subject.Contains(searchText, StringComparison.OrdinalIgnoreCase);
    }
}
注意事项
  • 过滤用户输入内容时要做特殊字符转义,避免出现语法错误
  • 如需同时过滤发件人、主题等多个字段,可修改Filter条件为Subject LIKE '%xxx%' OR From LIKE '%xxx%'即可

内容的提问来源于stack exchange,提问作者eugenes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 20:54:02