实现类似Excel的筛选

以下是在 DataGridView 中实现类似 Excel 下拉筛选功能的解决方案:

解决思路

  1. 为 DataGridView 的列添加 DataGridViewComboBoxColumn 类型的列,用于显示下拉筛选列表。
  2. 为 DataGridView 的 ColumnHeaderMouseClick 事件添加处理程序,当用户点击列头时,显示下拉筛选菜单。
  3. 根据列的数据生成下拉列表的选项。

实现代码

csharp 复制代码
using System;
using System.Collections.Generic;
using System.Windows.Forms;

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        // 假设你已经将 DataGridView 绑定到数据源,例如通过 FillDataGridView 方法
        FillDataGridView();
    }

    private void FillDataGridView()
    {
        // 假设你有一个数据源,这里使用一个简单的 List 作为示例
        List<TempTaskInfoTable> list = new List<TempTaskInfoTable>();
        // 添加一些数据到列表中
        list.Add(new TempTaskInfoTable { sampleName = "Sample 1", priority = "High" });
        list.Add(new TempTaskInfoTable { sampleName = "Sample 2", priority = "Medium" });
        list.Add(new TempTaskInfoTable { sampleName = "Sample 3", priority = "Low" });

        BindingSource dataSource = new BindingSource();
        dataSource.DataSource = list;
        dataGridView1.DataSource = dataSource;
    }

    private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
    {
        DataGridViewColumn column = dataGridView1.Columns[e.ColumnIndex];
        if (column is DataGridViewComboBoxColumn)
        {
            return;
        }
        // 生成下拉列表的选项
        List<string> options = new List<string>();
        foreach (DataGridViewRow row in dataGridView1.Rows)
        {
            if (row.Cells[e.ColumnIndex].Value!= null)
            {
                string value = row.Cells[e.ColumnIndex].Value.ToString();
                if (!options.Contains(value))
                {
                    options.Add(value);
                }
            }
        }

        DataGridViewComboBoxColumn comboBoxColumn = new DataGridViewComboBoxColumn();
        comboBoxColumn.DataSource = options;
        comboBoxColumn.HeaderText = column.HeaderText;
        comboBoxColumn.Name = column.Name;
        comboBoxColumn.DataPropertyName = column.DataPropertyName;

        // 替换原来的列
        int columnIndex = e.ColumnIndex;
        dataGridView1.Columns.RemoveAt(columnIndex);
        dataGridView1.Columns.Insert(columnIndex, comboBoxColumn);
    }
}


public class TempTaskInfoTable
{
    public string sampleName { get; set; }
    public string priority { get; set; }
}

代码解释

  1. 初始化和数据绑定部分 :
    • 在 FillDataGridView 方法中,创建一个 List<TempTaskInfoTable> 作为数据源,并添加一些数据。
    • 使用 BindingSource 将数据绑定到 dataGridView1。
  2. 列头点击事件处理部分 :
    • 在 dataGridView1_ColumnHeaderMouseClick 事件处理程序中:
      • 获取用户点击的列。
      • 遍历 dataGridView1 的行,收集该列的所有唯一值,存储在 options 列表中。
      • 创建一个 DataGridViewComboBoxColumn,将 options 作为其数据源。
      • 设置 DataGridViewComboBoxColumn 的 HeaderText、Name 和 DataPropertyName 与原列相同。
      • 移除原列,并将 DataGridViewComboBoxColumn 插入到原列的位置。

使用说明

  1. 在你的 Windows 窗体应用程序中,将上述代码添加到相应的 Form 类中。
  2. 确保你已经在窗体中添加了 dataGridView1 控件。
  3. 为 dataGridView1 的 ColumnHeaderMouseClick 事件关联 dataGridView1_ColumnHeaderMouseClick 方法。
  4. 当用户点击 DataGridView 的列头时,该列将被替换为一个下拉列表,下拉列表的选项是该列的唯一值。

优化建议

  1. 保存原始列的信息,当用户取消筛选时,可以将列恢复为原始状态。
  2. 对于大量数据,可以使用 HashSet<string> 来存储唯一值,提高性能。
csharp 复制代码
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    DataGridViewColumn column = dataGridView1.Columns[e.ColumnIndex];
    if (column is DataGridViewComboBoxColumn)
    {
        return;
    }
    // 生成下拉列表的选项
    HashSet<string> options = new HashSet<string>();
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (row.Cells[e.ColumnIndex].Value!= null)
        {
            string value = row.Cells[e.ColumnIndex].Value.ToString();
            options.Add(value);
        }
    }

    DataGridViewComboBoxColumn comboBoxColumn = new DataGridViewComboBoxColumn();
    comboBoxColumn.DataSource = new List<string>(options);
    comboBoxColumn.HeaderText = column.HeaderText;
    comboBoxColumn.Name = column.Name;
    comboBoxColumn.DataPropertyName = column.DataPropertyName;

    // 替换原来的列
    int columnIndex = e.ColumnIndex;
    dataGridView1.Columns.RemoveAt(columnIndex);
    dataGridView1.Columns.Insert(columnIndex, comboBoxColumn);
}
  1. 可以添加一个按钮或菜单项,用于清除筛选条件,将 DataGridViewComboBoxColumn 恢复为原列。
  2. 对于筛选逻辑,可以添加筛选功能,根据用户选择的下拉选项过滤数据,可使用 DataView 和 RowFilter 实现。
csharp 复制代码
private void dataGridView1_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
{
    DataGridViewColumn column = dataGridView1.Columns[e.ColumnIndex];
    if (column is DataGridViewComboBoxColumn)
    {
        return;
    }
    HashSet<string> options = new HashSet<string>();
    foreach (DataGridViewRow row in dataGridView1.Rows)
    {
        if (row.Cells[e.ColumnIndex].Value!= null)
        {
            string value = row.Cells[e.ColumnIndex].Value.ToString();
            options.Add(value);
        }
    }

    DataGridViewComboBoxColumn comboBoxColumn = new DataGridViewComboBoxColumn();
    comboBoxColumn.DataSource = new List<string>(options);
    comboBoxColumn.HeaderText = column.HeaderText;
    comboBoxColumn.Name = column.Name;
    comboBoxColumn.DataPropertyName = column.DataPropertyName;
    comboBoxColumn.ValueMember = column.DataPropertyName;
    comboBoxColumn.DisplayMember = column.DataPropertyName;
    comboBoxColumn.SelectedIndexChanged += ComboBoxColumn_SelectedIndexChanged;

    // 替换原来的列
    int columnIndex = e.ColumnIndex;
    dataGridView1.Columns.RemoveAt(columnIndex);
    dataGridView1.Columns.Insert(columnIndex, comboBoxColumn);
}

private void ComboBoxColumn_SelectedIndexChanged(object sender, EventArgs e)
{
    DataGridViewComboBoxColumn comboBoxColumn = (DataGridViewComboBoxColumn)sender;
    string selectedValue = comboBoxColumn.SelectedValue.ToString();
    DataView dataView = (DataView)bindingSource.DataSource;
    if (string.IsNullOrEmpty(selectedValue))
    {
        dataView.RowFilter = "";
    }
    else
    {
        dataView.RowFilter = $"{comboBoxColumn.DataPropertyName} = '{selectedValue}'";
    }
}

在上述代码中,为 DataGridViewComboBoxColumn 的 SelectedIndexChanged 事件添加了处理程序,根据用户的选择更新 RowFilter 以实现筛选功能。

注意事项

  1. 当处理用户选择时,需要确保数据类型匹配,避免类型转换异常。
  2. 对于复杂的数据类型,可能需要自定义 ToString 方法或使用其他数据转换方式。
  3. 当处理大量数据时,需要考虑性能问题,例如在生成下拉列表选项时,可以使用异步操作。
相关推荐
Data-Miner21 小时前
一个省大模型积分的 Excel 数据处理方案:脱敏生成逻辑,脚本复用把 token 降到 0
人工智能·windows·excel
Logic1012 天前
表格智能记账3 销售与库存智能联动,自动标红库存预警
excel·条件格式·excel技巧·vlookup·sumif
技术小甜甜2 天前
【Copilot】能选 Claude 和 GPT-6 了,Excel 分析该交给谁
gpt·excel·copilot·claude·microsoft365·gpt-6
小白今天也很酷3 天前
MCXN947更新板载DAP_Link固件的方法
c语言·python·单片机·ubuntu·excel·1024程序员节
ratel️4 天前
小墨析 · Office Agent 日常办公不烧心
python·langchain·word·excel·fastapi·js·ppt
Logic1014 天前
没有TextSplit函数的老版本也能拆分单元格的内容
excel·拆分数据·excel技巧·数据拆分·拆分单元格·textsplit·旧版excel
2601_967987374 天前
你们都用Python实现了哪些自动化办公?
python·excel·自动化办公·1024程序员节·学习资料·跨平台操作
城数派4 天前
1901-2025年中国省/市/县三级逐月平均气温数据Excel+Shp格式
excel
gtstore5 天前
从 Excel 迁移到仓库管理系统的数据准备与切换方案
excel·数据迁移·仓库管理系统·进销存·信息化实施
ms365copilot5 天前
我不再自己做 Word、Excel 和 PPT 了,我让 Copilot 直接帮我创建 (1)
word·powerpoint·excel·copilot