繁体   English   中英

使用文本框过滤 DataGridView

[英]Filter DataGridView with TextBox

我有一个DataGridView和一个TextBox 我需要使用TextBox过滤DataGridViewSQL中 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM