C#实现只读DataGridView内置特定列搜索(无需TextBox)
I get it, you want to let users type directly into your read-only DataGridView to filter rows where the Name column matches their input—no extra TextBox needed. Here's a step-by-step solution that works for both bound and unbound DataGridViews:
Step 1: Set Up Variables and Initialize the Control
First, add form-level variables to track the search text and a timer to reset the search after inactivity. Then set up your DataGridView (example includes sample data for testing):
using System; using System.Data; using System.Windows.Forms; namespace DataGridViewSearch { public partial class MainForm : Form { private string _currentSearch = string.Empty; private Timer _searchResetTimer; public MainForm() { InitializeComponent(); Load += MainForm_Load; } private void MainForm_Load(object sender, EventArgs e) { // Configure the search reset timer (clears search after 2 seconds of inactivity) _searchResetTimer = new Timer { Interval = 2000 // Adjust this value (in milliseconds) as needed }; _searchResetTimer.Tick += SearchResetTimer_Tick; // Set up sample DataGridView (replace with your actual data source) DataTable studentTable = new DataTable(); studentTable.Columns.Add("Roll No", typeof(int)); studentTable.Columns.Add("Name", typeof(string)); studentTable.Columns.Add("Surname", typeof(string)); // Add sample rows studentTable.Rows.Add(1, "Mohan", "Sharma"); studentTable.Rows.Add(2, "Rahul", "Verma"); studentTable.Rows.Add(3, "Mohan", "Singh"); studentTable.Rows.Add(4, "Priya", "Mehta"); // Bind data to DataGridView and make it read-only dataGridView1.DataSource = studentTable; dataGridView1.ReadOnly = true; dataGridView1.KeyPress += DataGridView1_KeyPress; // Ensure the DataGridView has focus to receive key presses dataGridView1.Focus(); } } }
Step 2: Capture Key Presses to Build Search Text
Handle the KeyPress event to build the search string (including backspace support):
private void DataGridView1_KeyPress(object sender, KeyPressEventArgs e) { // Handle backspace to remove the last character from the search text if (e.KeyChar == (char)Keys.Back) { if (_currentSearch.Length > 0) { _currentSearch = _currentSearch.Substring(0, _currentSearch.Length - 1); } } // Add printable characters (letters, numbers, spaces) to the search text else if (char.IsLetterOrDigit(e.KeyChar) || char.IsWhiteSpace(e.KeyChar)) { _currentSearch += e.KeyChar; } // Restart the timer to reset search if user stops typing _searchResetTimer.Stop(); _searchResetTimer.Start(); // Apply the filter immediately after each key press ApplySearchFilter(); }
Step 3: Reset Search After Inactivity
The timer clears the search text if the user stops typing for the specified interval:
private void SearchResetTimer_Tick(object sender, EventArgs e) { _currentSearch = string.Empty; ApplySearchFilter(); _searchResetTimer.Stop(); }
Step 4: Apply the Search Filter
This method filters rows based on the current search text. It supports both bound (DataTable) and unbound DataGridViews:
private void ApplySearchFilter() { // Handle bound DataGridView (connected to DataTable) if (dataGridView1.DataSource is DataTable studentTable) { DataView studentView = studentTable.DefaultView; if (string.IsNullOrEmpty(_currentSearch)) { // Show all rows if search text is empty studentView.RowFilter = string.Empty; } else { // Escape single quotes to avoid syntax errors in RowFilter string escapedSearch = _currentSearch.Replace("'", "''"); // Option 1: Exact match (case-insensitive) studentView.RowFilter = $"UPPER(Name) = '{escapedSearch.ToUpper()}'"; // Option 2: Partial match (contains search text, case-insensitive) // studentView.RowFilter = $"UPPER(Name) LIKE '%{escapedSearch.ToUpper()}%'"; } } // Handle unbound DataGridView else { foreach (DataGridViewRow row in dataGridView1.Rows) { if (!row.IsNewRow) { string nameValue = row.Cells["Name"].Value?.ToString() ?? string.Empty; if (string.IsNullOrEmpty(_currentSearch)) { row.Visible = true; } else { // Option 1: Exact match (case-insensitive) row.Visible = nameValue.Equals(_currentSearch, StringComparison.OrdinalIgnoreCase); // Option 2: Partial match (contains search text, case-insensitive) // row.Visible = nameValue.Contains(_currentSearch, StringComparison.OrdinalIgnoreCase); } } } } }
Key Notes
- Case Sensitivity: The code uses case-insensitive matching by default. Adjust the
StringComparisonor removeUPPER()calls if you need case-sensitive search. - Special Characters: The
escapedSearchvariable handles single quotes in the search text to prevent syntax errors in the DataView RowFilter. - Timer Interval: Modify the
_searchResetTimer.Intervalvalue to change how long the search stays active after the user stops typing (2000ms = 2 seconds). - Focus: Make sure the DataGridView has focus when the form loads so it can receive key presses.
This solution lets users type directly into the read-only DataGridView, filters rows in real-time, and clears the search automatically after inactivity—perfect for your use case!
内容的提问来源于stack exchange,提问作者Mohan Lalwani

