Estoy desarrollando control de usuario en C# Visual Studio 2010 - una especie de cuadro de diálogo de "búsqueda rápida" para filtrar datagridview. Debería funcionar para 3 tipos de fuentes de datos datagridview: DataTable, DataBinding y DataSet. Mi problema es filtrar DataTable del objeto DataSet, que se muestra en DataGridView.Filtrar DataGridView sin cambiar el origen de datos
Podría ser de 3 casos (ejemplos de aplicación WinForm estándar con DataGridView y TextBox en él) - 2 primeros están trabajando bien, no tengo problema con una tercera:
1. datagridview.DataSource = dataTable: funciona
para que pueda filtrar estableciendo: 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: funciona
por lo que se puede filtrar mediante el establecimiento de: bindingSource.Filter = "país como '% 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 = dataSource; datagridview.DataMember = "TableName": no funciona
Ocurre cuando diseña una tabla con el diseñador: coloque el DataSet de la caja de herramientas en el formulario, agregue dataTable y luego establezca datagridview.DataSource = dataSource; y datagridview.DataMember = "TableName".
código de abajo simula estas operaciones:
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());
}
Si el resultado es que - si bien se filtra tabla de datos (ds.Tables [0] cambios .DefaultView.Count), DataGridView no se actualiza ... he sido buscando un largo tiempo para cualquier solución, pero el problema es que DataSource no puede cambiar - como es control adicional, no quiero que se estropee con el código del programador.
Sé posibles soluciones son:
- para unirse DataTable del conjunto de datos utilizando DataBinding y utilizarlo como ejemplo 2: pero es responsabilidad del programador durante la escritura de código,
- para cambiar dataSource a BindingSource, dataGridView.DataSource = dataSet.Tables [0], o DefaultView programáticamente: sin embargo, cambia el DataSource. Así que la solución:
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());
}
no es aceptable, ya que se ve en dataSource del cuadro de mensaje está cambiando ...
yo no quiero hacer eso, porque es posible que un programador escribe código similar al siguiente:
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
}
Puede hacerlo, ya que diseñó DataGridView con DataSet y DataMember en el diseñador. El código se compilará, sin embargo, después de usar un filtro, lanzará una excepción ...
Entonces la pregunta es: ¿cómo puedo filtrar DataTable en DataSet y mostrar los resultados en DataGridView sin cambiar DataSource a otro? ¿Por qué puedo filtrar DataTable del ejemplo 1 directamente, mientras que el filtrado de DataTable de DataSet no funciona? ¿Tal vez no sea DataTable enlazado a DataGridView en ese caso?
Tenga en cuenta, que mi problema lleva desde el diseño de los problemas, por lo que la solución debe trabajar en el ejemplo 3.
Mis 2 centavos, además de todos los comentarios y soluciones valiosas. Aquí hay un [artículo] (http://10tec.com/articles/datagridview-filter.aspx) que describe los pros y los contras del filtrado DataGridView enlazado a datos de esta manera y le brinda algunas ideas de cómo hacerlo mejor. – TecMan
Disculpe la repetición pero creo que mi propuesta no funciona todo el tiempo. De hecho, a veces se levanta una excepción, que mi código es poco probable. Intentando filtrar con un bindingSource tienes todas las posibilidades de hacer un buen código. Como fecha: bindingSource.Filter = string.Format ..... –