Фильтрация DataGridView без изменения источника данных

Я разрабатываю пользовательский элемент управления в C # Visual Studio 2010 - своего рода текстовое поле «быстрого поиска» для фильтрации datagridview. Он должен работать для 3 типов источников данных datagridview: DataTable, DataBinding и DataSet. m разрабатывает пользовательский элемент управления в C # Visual Studio 2010 - своего рода текстовое поле «быстрого поиска» для фильтрации datagridview. Он должен работать для 3 типов источников данных datagridview: DataTable, DataBinding и DataSet. m разрабатывает пользовательский элемент управления в C # Visual Studio 2010 - своего рода текстовое поле «быстрого поиска» для фильтрации datagridview. Он должен работать для 3 типов источников данных datagridview: DataTable, DataBinding и DataSet. Моя проблема связана с фильтрацией DataTable из объекта DataSet, который отображается в DataGridView.

Может быть 3 случая (примеры для стандартного приложения WinForm с DataGridView и TextBox на нем) - первые 2 работают нормально, у меня проблема с третьим один:

1. datagridview.DataSource = dataTable: он работает
, поэтому я могу фильтровать, установив: dataTable.DefaultView.RowFilter = "country LIKE '% s%'";

DataTable dt = new DataTable();

private void Form1_Load(object sender, EventArgs e)
{
    dt.Columns.Add("id", typeof(int));
    dt.Columns.Add("country", typeof(string));

    dt.Rows.Add(new object[] { 1, "Belgium" });
    dt.Rows.Add(new object[] { 2, "France" });
    dt.Rows.Add(new object[] { 3, "Germany" });
    dt.Rows.Add(new object[] { 4, "Spain" });
    dt.Rows.Add(new object[] { 5, "Switzerland" });
    dt.Rows.Add(new object[] { 6, "United Kingdom" });

    dataGridView1.DataSource = dt;
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("DataSource type BEFORE = " + dataGridView1.DataSource.GetType().ToString());

    dt.DefaultView.RowFilter = string.Format("country LIKE '%{0}%'", textBox1.Text);

    MessageBox.Show("DataSource type AFTER = " + dataGridView1.DataSource.GetType().ToString());
} 

2. datagridview.DataSource = bindingSource: он работает
, поэтому я могу фильтровать, установив: bindingSource.Filter = "country LIKE '% s%'";

DataTable dt = new DataTable();
BindingSource bs = new BindingSource();

private void Form1_Load(object sender, EventArgs e)
{
    dt.Columns.Add("id", typeof(int));
    dt.Columns.Add("country", typeof(string));

    dt.Rows.Add(new object[] { 1, "Belgium" });
    dt.Rows.Add(new object[] { 2, "France" });
    dt.Rows.Add(new object[] { 3, "Germany" });
    dt.Rows.Add(new object[] { 4, "Spain" });
    dt.Rows.Add(new object[] { 5, "Switzerland" });
    dt.Rows.Add(new object[] { 6, "United Kingdom" });

    bs.DataSource = dt;
    dataGridView1.DataSource = bs;
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("DataSource type BEFORE = " + dataGridView1.DataSource.GetType().ToString());

    bs.Filter = string.Format("country LIKE '%{0}%'", textBox1.Text);

    MessageBox.Show("DataSource type AFTER = " + dataGridView1.DataSource.GetType().ToString());
}

3. datagridview.DataSource = источник данных; datagridview.DataMember = "TableName": это не работает
Это происходит, когда вы создаете таблицу с помощью конструктора: поместите DataSet из панели инструментов в форму, добавьте к ней dataTable и затем установите datagridview. Источник данных = источник данных; и datagridview.DataMember = "TableName".
Код ниже симулирует эти операции:

DataSet ds = new DataSet();
DataTable dt = new DataTable();

private void Form1_Load(object sender, EventArgs e)
{
    dt.Columns.Add("id", typeof(int));
    dt.Columns.Add("country", typeof(string));

    dt.Rows.Add(new object[] { 1, "Belgium" });
    dt.Rows.Add(new object[] { 2, "France" });
    dt.Rows.Add(new object[] { 3, "Germany" });
    dt.Rows.Add(new object[] { 4, "Spain" });
    dt.Rows.Add(new object[] { 5, "Switzerland" });
    dt.Rows.Add(new object[] { 6, "United Kingdom" });

    ds.Tables.Add(dt);
    dataGridView1.DataSource = ds;
    dataGridView1.DataMember = dt.TableName;
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("DataSource type BEFORE = " + dataGridView1.DataSource.GetType().ToString());  
    //it is not working
    ds.Tables[0].DefaultView.RowFilter = string.Format("country LIKE '%{0}%'", textBox1.Text);

    MessageBox.Show("DataSource type AFTER = " + dataGridView1.DataSource.GetType().ToString());
}

Если вы его протестируете - хотя datatable отфильтрован (ds.Tables [0] .DefaultView.Count изменяется), datagridview не обновляется ... Я давно искал какое-нибудь решение, но проблема в том, что DataSource не может изменить - поскольку это дополнительный элемент управления, я не хочу, чтобы он испортил код программиста.

Я знаю возможные решения:
- привязать DataTable из DataSet с помощью DataBinding и использовать его в качестве примера 2: но это зависит от программиста во время написания кода,
- для изменения источника данных на BindingSource, dataGridView.DataSource = dataSet.Tables [0] или на DefaultView программно: однако это изменяет источник данных. Итак, решение:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("DataSource type BEFORE = " + dataGridView1.DataSource.GetType().ToString(), ds.Tables[0].DefaultView.Count.ToString());

    DataView dv = ds.Tables[0].DefaultView;
    dv.RowFilter = string.Format("country LIKE '%{0}%'", textBox1.Text);
    dataGridView1.DataSource = dv;

    MessageBox.Show("DataSource type AFTER = " + dataGridView1.DataSource.GetType().ToString(), ds.Tables[0].DefaultView.Count.ToString());
}

неприемлемо, как вы видите в сообщении MessageBox, источник данных меняется ...

Я не хочу этого делать, потому что, возможно, программист напишет код, подобный этому:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    MessageBox.Show("DataSource type BEFORE = " + dataGridView1.DataSource.GetType().ToString(), ds.Tables[0].DefaultView.Count.ToString());

    DataSet dsTmp = (DataSet)(dataGridView1.DataSource);   //<--- it is OK 

    DataView dv = ds.Tables[0].DefaultView;
    dv.RowFilter = string.Format("country LIKE '%{0}%'", textBox1.Text);
    dataGridView1.DataSource = dv;   //<--- here the source is changeing from DataSet to DataView

    MessageBox.Show("DataSource type AFTER = " + dataGridView1.DataSource.GetType().ToString(), ds.Tables[0].DefaultView.Count.ToString());

    dsTmp = (DataSet)(dataGridView1.DataSource);    //<-- throws an exception: Unable to cast object DataView to DataSet
}

Он может сделайте это, поскольку он разработал DataGridView с DataSet и DataMember в дизайнере. Код будет скомпилирован, однако после использования фильтра он вызовет исключение ...

Итак, возникает вопрос: как мне отфильтровать DataTable в DataSet и показать результаты в DataGridView, не меняя DataSource на другой? Почему я могу напрямую фильтровать DataTable из примера 1, а фильтрация DataTable из DataSet не работает? Может быть, в этом случае DataTable не привязан к DataGridView?

Обратите внимание, что моя проблема связана с проблемами проектирования, поэтому решение ДОЛЖНО РАБОТАТЬ в примере 3.

89
задан madster 6 July 2016 в 15:51
поделиться