[英]Filter DataGridView with TextBox
我有一個DataGridView
和一個TextBox
。 我需要使用TextBox
過濾DataGridView
中SQL
中 DB 中的值。
像這樣的東西:
這是我的代碼:
public partial class Form1 : Form
{
private DataSet dataSet;
private SqlDataAdapter adapter;
private BindingSource bindingSource = new BindingSource();
private DataView dataView = new DataView();
public Form1()
{
InitializeComponent();
}
private void GetData(string valor)
{
try
{
// Initialize the DataSet.
dataSet = new DataSet();
dataSet.Tables.Add(new DataTable());
dataSet.Tables[0].Columns.Add("numberAsString", typeof(string));
dataSet.Locale = CultureInfo.InvariantCulture;
// Create the connection string for the AdventureWorks sample database.
string connectionString = "connection ";
// Create the command strings for querying the Contact table.
string contactSelectCommand = "SELECT Titulo as Título FROM V_CuetaWeb WHERE Titulo LIKE ('" + valor + "%') GROUP BY titulo ORDER BY titulo DESC";
// Create the contacts data adapter.
adapter = new SqlDataAdapter(
contactSelectCommand,
connectionString);
// Create a command builder to generate SQL update, insert, and
// delete commands based on the contacts select command. These are used to
// update the database.
SqlCommandBuilder contactsCommandBuilder = new SqlCommandBuilder(adapter);
// Fill the data set with the contact information.
adapter.Fill(dataSet, "V_CuetaWeb");
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
}
private void Form1_Load(object sender, EventArgs e)
{
DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
chk.HeaderText = "Seleccione";
chk.Name = "check";
dtgTitulo.Columns.Add(chk);
dtgTitulo.AllowUserToAddRows = false;
dataSet = new DataSet();
GetData(txtFiltroTitulo.Text);
dtgTitulo.DataSource = bindingSource;
// Create a LinqDataView from a LINQ to DataSet query and bind it
// to the Windows forms control.
EnumerableRowCollection<DataRow> contactQuery = from row in dataSet.Tables["V_CuetaWeb"].AsEnumerable()
orderby row.Field<double>("Título") descending
select row;
dataView = contactQuery.AsDataView();
// Bind the DataGridView to the BindingSource.
bindingSource.DataSource = dataView;
string value = "";
dtgTitulo.DataSource = bindingSource;
bindingSource.Filter = "Título LIKE('" + Convert.ToInt64(value) + "%')";
dtgTitulo.AutoResizeColumns();
}
private void txtFiltroTitulo_TextChanged(object sender, EventArgs e)
{
GetData(txtFiltroTitulo.Text);
}
}
但不起作用,因為“título”是 SQL 中的浮點數據。 那么,有什么依據嗎?
將 Titulo 轉換為 varchar,就像這樣......
SELECT … WHERE CAST(Titulo AS varchar(50)) LIKE ('" + valor + "%') …
而過濾器可能是這樣的......
bindingSource.Filter = "CONVERT(Título, 'System.String') LIKE('" + Convert.ToInt64(value) + "%')";
你描述的問題是雙重的。 首先,代碼是將復選框列“添加”到DataGridView
本身! 這是一個問題,因為網格的DataSource
不“知道”這個“添加”的列。 因此,當您對數據源應用“過濾器”時,該過濾器不會知道復選框列,並且顯然不會維護/關心“哪些”復選框已被選中或未選中。 要維護過濾器中的復選框,復選框列需要位於數據源本身中。
其次,當用戶更改過濾器文本框中的文本時,代碼似乎在重新查詢數據庫。 這很奇怪,我敢打賭你可能想重新考慮一下。 示例:每次用戶在文本框中鍵入一個字符時,代碼都會重新查詢數據庫。 如果用戶想“輸入”123,那么……當用戶輸入“1”時,數據庫被查詢,當用戶輸入“2”時再次查詢,當用戶輸入“3”時再次查詢。 這顯然是不必要的,可以歸類為破壞數據庫。
不要誤會我的意思,從某種意義上說,當用戶鍵入“1”,然后是“2”,最后是“3”時,我們確實想要“過濾”數據……您只是不想重新查詢數據庫來做到這一點。 為了避免這種數據庫破壞,代碼可以創建一個保存原始數據的“全局”變量,然后,當我們要過濾數據時,您可以從原始數據中獲取過濾后的副本,而不是重新查詢數據庫. 這意味着代碼只會查詢數據庫一次。
鑒於此,下面的代碼演示了將復選框列添加到網格DataSource
DataTable
......而不是添加到網格本身。 這將在過濾時保留復選框。 此外,該代碼不會在鍵入每個過濾字符時重新查詢數據庫,而是過濾原始數據源。 這是通過從原始數據創建一個新的DataView
然后針對輸入的每個字符過濾該DataView
來實現的。
希望這有幫助並且有意義。
表單的加載方法可能看起來像……
DataSet ds;
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
ds = new DataSet();
ds.Tables.Add(GetDataFromDB());
ds.Tables[0].Columns.Add("Select", typeof(bool));
dataGridView1.DataSource = ds.Tables[0];
}
GetDataFromDB
返回一個DataTable
,其中有一 (1) 個名為“Title”的列,其類型為double
。 然后我們將一列添加到從數據庫返回的DataTable
。 此列名為“Select”,類型為bool
... 復選框列。 現在,篩選時將保留復選框。
最后,當用戶在過濾器文本框中輸入文本時“過濾”數據......
private void textBox1_TextChanged(object sender, EventArgs e) {
DataView dv = new DataView(ds.Tables[0]);
if (double.TryParse(textBox1.Text, out double value)) {
dv.RowFilter = "CONVERT(Title, 'System.String') LIKE('" + value + "%')";
}
dataGridView1.DataSource = dv;
}
在這里,我們從原始數據創建一個“新” DataView
,然后使用文本框中的文本過濾該DataView
,然后將網格設置為這個新DataView
。 請注意, double.TryParse
方法用於過濾掉用戶鍵入的任何不是數字或為空的文本,在這種情況下,過濾器將顯示所有數據。
為了完成這個例子,下面是一種獲取一些測試數據進行測試的方法。
private DataTable GetDataFromDB() {
DataTable dt = new DataTable();
dt.TableName = "Titles";
Random rand = new Random();
dt.Columns.Add("Title", typeof(double));
for (int i = 0; i < 3000; i++) {
dt.Rows.Add(rand.Next(0, 1000));
}
return dt;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.