[英]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.