Фильтр DataGridView с TextBox - PullRequest
2 голосов
/ 10 марта 2020

У меня есть DataGridView и TextBox. Мне нужно отфильтровать значения из БД в SQL в DataGridView с TextBox.

Примерно так:

enter image description here

Это мой код:

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. Итак, любая суеверия?

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Проблема, которую вы описываете, имеет две стороны. Во-первых, код «добавляет» столбец флажка к самому 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];
}

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * DataTable 1 * Затем мы добавляем столбец к DataTable, возвращаемому из базы данных. Этот столбец называется «Выбрать» и имеет тип 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;
}
1 голос
/ 10 марта 2020

Принесите Titulo к varchar, что-то вроде этого ...

SELECT … WHERE CAST(Titulo AS varchar(50)) LIKE ('" + valor + "%') … 

И фильтр может быть что-то вроде этого ...

bindingSource.Filter = "CONVERT(Título, 'System.String') LIKE('" + Convert.ToInt64(value) + "%')";
...