c# - filas - Filtrar DataGridView sin cambiar el origen de datos
filtrar fechas en un datagridview c# (7)
// "Comment" Filter datagrid sin cambiar el conjunto de datos, funciona perfectamente.
(dg.ItemsSource as ListCollectionView).Filter = (d) =>
{
DataRow myRow = ((System.Data.DataRowView)(d)).Row;
if (myRow["FName"].ToString().ToUpper().Contains(searchText.ToString().ToUpper()) || myRow["LName"].ToString().ToUpper().Contains(searchText.ToString().ToUpper()))
return true; //if want to show in grid
return false; //if don''t want to show in grid
};
Estoy desarrollando control de usuario en C # Visual Studio 2010 - una especie de cuadro de texto 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 con el filtrado de 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 en él): los primeros 2 funcionan bien, tengo un problema con el tercero:
1. datagridview.DataSource = dataTable: funciona
entonces puedo 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
entonces 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 con el diseñador: coloque el conjunto de datos de la caja de herramientas en el formulario, agréguelo a la tabla de datos y luego configure datagridview.DataSource = dataSource; y datagridview.DataMember = "TableName".
El siguiente código 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 se filtra la tabla de datos (cambios en ds.Tables [0] .DefaultView.Count), datagridview no se actualiza ... He estado buscando un largo tiempo para cualquier solución, pero el problema es que DataSource no puede cambio , ya que es un control adicional, no quiero que se estropee con el código del programador.
Sé que las posibles soluciones son:
- para enlazar DataTable desde DataSet usando DataBinding y usarlo como ejemplo 2: pero depende del programador durante la escritura del código,
- para 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 DataBox''s DataSource está cambiando ...
No quiero hacer eso, porque es posible que un programador escriba 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 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 se debe al diseño de problemas, por lo que la solución DEBE FUNCIONAR en el ejemplo 3.
Acabo de pasar una hora con un problema similar. Para mí, la respuesta resultó ser embarazosamente simple.
(dataGridViewFields.DataSource as DataTable).DefaultView.RowFilter = string.Format("Field = ''{0}''", textBoxFilter.Text);
Desarrollé una declaración genérica para aplicar el filtro:
string rowFilter = string.Format("[{0}] = ''{1}''", columnName, filterValue);
(myDataGridView.DataSource as DataTable).DefaultView.RowFilter = rowFilter;
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:
rowFilter += string.Format(" OR [{0}] = ''{1}''", columnName, additionalFilterValue);
Encontré una manera simple de solucionar ese problema. En binding datagridview usted acaba de hacer: datagridview.DataSource = dataSetName.Tables["TableName"];
Si codificas como:
datagridview.DataSource = dataSetName;
datagridview.DataMember = "TableName";
el datagridview nunca volverá a cargar datos al filtrar.
Puede crear un objeto DataView partir de su fuente de datos. Esto le permitiría filtrar y ordenar sus datos sin modificar directamente la fuente de datos.
Además, recuerde llamar a dataGridView1.DataBind();
después de configurar la fuente de datos.
Tengo una propuesta más clara sobre la búsqueda automática en un DataGridView
esto es un ejemplo
private void searchTb_TextChanged(object sender, EventArgs e)
{
try
{
(lecteurdgview.DataSource as DataTable).DefaultView.RowFilter = String.IsNullOrEmpty(searchTb.Text) ?
"lename IS NOT NULL" :
String.Format("lename LIKE ''{0}'' OR lecni LIKE ''{1}'' OR ledatenais LIKE ''{2}'' OR lelieu LIKE ''{3}''", searchTb.Text, searchTb.Text, searchTb.Text, searchTb.Text);
}
catch (Exception ex) {
MessageBox.Show(ex.StackTrace);
}
}
Una manera más simple y que es transversal a los datos, es ocultar las líneas con la propiedad visible.
// Mostrar todas las líneas
for (int u = 0; u < dataGridView3.RowCount; u++)
{
dataGridView3.Rows[u].Visible = true;
x++;
}
// Ocultar los que desee con el filtro que desea.
for (int u = 0; u < dataGridView3.RowCount; u++)
{
if (dataGridView3.Rows[u].Cells[4].Value == "The filter string")
{
dataGridView3.Rows[u].Visible = true;
}
else
{
dataGridView3.Rows[u].Visible = false;
}
}
Solo una idea ... para mi trabajo.