以下是在 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
方法或使用其他数据转换方式。 - 当处理大量数据时,需要考虑性能问题,例如在生成下拉列表选项时,可以使用异步操作。