Estoy desarrollando control de usuario en C # Visual Studio 2010, una especie de cuadro de texto de "búsqueda rápida" para filtrar la vista de cuadrícula de datos. Debería funcionar para 3 tipos de fuentes de datos de datagridview: DataTable, DataBinding y DataSet. Mi problema es filtrar DataTable del objeto DataSet, que se muestra en DataGridView.
Podría haber 3 casos (ejemplos para la aplicación WinForm estándar con DataGridView y TextBox): los primeros 2 funcionan bien, tengo un problema con el tercero:
1. datagridview.DataSource = dataTable: funciona
así que puedo filtrar configurando: dataTable.DefaultView.RowFilter = "país 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,
así que puedo filtrar estableciendo: 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 = dataSource; datagridview.DataMember = "TableName": no funciona
Sucede cuando diseña una tabla usando el diseñador: coloque el DataSet de la caja de herramientas en el formulario, agregue dataTable y luego configure datagridview.DataSource = dataSource; y datagridview.DataMember = "TableName".
El código siguiente 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 lo prueba, aunque la tabla de datos está filtrada (ds.Tables [0] .DefaultView.Count cambia), la vista de cuadrícula de datos no se actualiza ... He estado buscando durante mucho tiempo alguna solución, pero el problema es que DataSource no puede cambiar - ya que es un control adicional, no quiero que se estropee con el código del programador.
Sé que las posibles soluciones son:
- enlazar DataTable desde DataSet usando DataBinding y usarlo como ejemplo 2: pero depende del programador durante la escritura del código,
- cambiar dataSource a BindingSource, dataGridView.DataSource = dataSet.Tables [0], o a DefaultView programáticamente: sin embargo, cambia el DataSource. Entonces 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, como puede ver en el DataSource de MessageBox está cambiando ...
No quiero hacer eso, porque es posible que un programador escriba un código similar a este:
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
}
Él puede hacer eso, 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, arrojará 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 filtrar DataTable de DataSet no funciona? ¿Quizás no está DataTable vinculado a DataGridView en ese caso?
Tenga en cuenta que mi problema se debe a problemas de diseño, por lo que la solución DEBE FUNCIONAR en el ejemplo 3.
Respuestas:
Acabo de pasar una hora en un problema similar. Para mí, la respuesta resultó ser vergonzosamente simple.
fuente
IBindingListView
según msdn.microsoft.com/en-us/library/…Object reference not set to an instance of an object.
para GridView.Desarrollé una declaración genérica para aplicar el filtro:
Los corchetes permiten espacios en el nombre de la columna.
Además, si desea incluir varios valores en su filtro, puede agregar la siguiente línea para cada valor adicional:
fuente
Una forma más sencilla es traspasar los datos y ocultar las líneas con la
Visible
propiedad.Solo una idea ... funciona para mí.
fuente
DataGridView
, esto funcionó perfectamente. :) Aunque usé unforeach
y asignado directamenterow.Visible = showAll || <condition>;
sin ningunoif
. EsoshowAll
es cierto si la cadena de filtro está vacía.Puede crear un objeto DataView desde su fuente de datos. Esto le permitiría filtrar y ordenar sus datos sin modificar directamente la fuente de datos.
Además, recuerde llamar
dataGridView1.DataBind();
después de configurar la fuente de datos.fuente
// "Comentario" Filtra la cuadrícula de datos sin cambiar el conjunto de datos, funciona perfectamente.
fuente
Tengo una propuesta más clara sobre la búsqueda automática en un DataGridView
esto es un ejemplo
fuente
Encontré una forma sencilla de solucionar ese problema. En el enlace datagridview, acaba de hacer:
datagridview.DataSource = dataSetName.Tables["TableName"];
Si codifica como:
la vista de cuadrícula de datos nunca volverá a cargar datos al filtrar.
fuente