以下是在 DataGridView
中实现类似 Excel 下拉筛选功能的解决方案:
解决思路
- 为
DataGridView
的列添加DataGridViewComboBoxColumn
类型的列,用于显示下拉筛选列表。 - 为
DataGridView
的ColumnHeaderMouseClick
事件添加处理程序,当用户点击列头时,显示下拉筛选菜单。 - 根据列的数据生成下拉列表的选项。
实现代码
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; }
}
代码解释
- 初始化和数据绑定部分:
- 在
FillDataGridView
方法中,创建一个List<TempTaskInfoTable>
作为数据源,并添加一些数据。 - 使用
BindingSource
将数据绑定到dataGridView1
。
- 在
- 列头点击事件处理部分:
- 在
dataGridView1_ColumnHeaderMouseClick
事件处理程序中:- 获取用户点击的列。
- 遍历
dataGridView1
的行,收集该列的所有唯一值,存储在options
列表中。 - 创建一个
DataGridViewComboBoxColumn
,将options
作为其数据源。 - 设置
DataGridViewComboBoxColumn
的HeaderText
、Name
和DataPropertyName
与原列相同。 - 移除原列,并将
DataGridViewComboBoxColumn
插入到原列的位置。
- 在
使用说明
- 在你的 Windows 窗体应用程序中,将上述代码添加到相应的
Form
类中。 - 确保你已经在窗体中添加了
dataGridView1
控件。 - 为
dataGridView1
的ColumnHeaderMouseClick
事件关联dataGridView1_ColumnHeaderMouseClick
方法。 - 当用户点击
DataGridView
的列头时,该列将被替换为一个下拉列表,下拉列表的选项是该列的唯一值。
优化建议
- 保存原始列的信息,当用户取消筛选时,可以将列恢复为原始状态。
- 对于大量数据,可以使用
HashSet<string>
来存储唯一值,提高性能。
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);
}
- 可以添加一个按钮或菜单项,用于清除筛选条件,将
DataGridViewComboBoxColumn
恢复为原列。 - 对于筛选逻辑,可以添加筛选功能,根据用户选择的下拉选项过滤数据,可使用
DataView
和RowFilter
实现。
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
以实现筛选功能。
注意事项
- 当处理用户选择时,需要确保数据类型匹配,避免类型转换异常。
- 对于复杂的数据类型,可能需要自定义
ToString
方法或使用其他数据转换方式。 - 当处理大量数据时,需要考虑性能问题,例如在生成下拉列表选项时,可以使用异步操作。