Je développe le contrôle utilisateur dans C # Visual Studio 2010 - une sorte de zone de texte "recherche rapide" pour filtrer les vues de données. Cela devrait fonctionner pour 3 types de sources de données datagridview: DataTable, DataBinding et DataSet. Mon problème concerne le filtrage de DataTable à partir de l'objet DataSet, qui est affiché sur DataGridView.
Il pourrait y avoir 3 cas (exemples pour l'application WinForm standard avec DataGridView et TextBox dessus) - les 2 premiers fonctionnent bien, j'ai un problème avec le 3ème:
1. datagridview.DataSource = dataTable: cela fonctionne
pour que je puisse filtrer en définissant: 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: il fonctionne
donc je peux filtrer en définissant: 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": cela ne fonctionne pas
Cela se produit lorsque vous concevez une table à l'aide du designer: mettez le DataSet de la boîte à outils sur formulaire, ajoutez-y dataTable puis définissez datagridview.DataSource = dataSource; et datagridview.DataMember = "TableName".
Le code ci-dessous prétend ces opérations:
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 vous le testez - bien que datatable soit filtré (ds.Tables [0] .DefaultView.Count change), datagridview n'est pas mis à jour ... Je cherche depuis longtemps une solution, mais le problème est que DataSource ne peut pas change - comme il s'agit d'un contrôle supplémentaire, je ne veux pas qu'il gâche le code du programmeur.
Je sais que les solutions possibles sont les suivantes:
- lier DataTable à partir de DataSet à l'aide de DataBinding et l'utiliser comme exemple 2: mais c'est au programmeur lors de l'écriture de code,
- de changer dataSource en BindingSource, dataGridView.DataSource = dataSet.Tables [0], ou à DefaultView par programme: cependant, il modifie le DataSource. Donc la solution:
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());
}
n'est pas acceptable, comme vous le voyez sur la dataSource de MessageBox est en train de changer ...
Je ne veux pas faire cela, car il est possible qu'un programmeur écrive un code similaire à celui-ci:
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
}
Il peut le faire, car il a conçu DataGridView avec DataSet et DataMember dans le concepteur. Le code sera compilé, cependant, après avoir utilisé un filtre, il lèvera une exception ...
La question est donc la suivante: comment filtrer DataTable dans DataSet et afficher les résultats sur DataGridView sans changer DataSource en un autre? Pourquoi puis-je filtrer directement DataTable à partir de l'exemple 1, alors que filtrer DataTable à partir de DataSet ne fonctionne pas? Peut-être que ce n'est pas DataTable lié à DataGridView dans ce cas?
Veuillez noter que mon problème provient des problèmes de conception, donc la solution DOIT FONCTIONNER sur l'exemple 3.
Réponses:
Je viens de passer une heure sur un problème similaire. Pour moi, la réponse s'est avérée extrêmement simple.
la source
IBindingListView
selon msdn.microsoft.com/en-us/libraryObject reference not set to an instance of an object.
pour le GridView.J'ai développé une déclaration générique pour appliquer le filtre:
Les crochets permettent des espaces dans le nom de la colonne.
De plus, si vous souhaitez inclure plusieurs valeurs dans votre filtre, vous pouvez ajouter la ligne suivante pour chaque valeur supplémentaire:
la source
Un moyen plus simple consiste à traverser les données et à masquer les lignes avec la
Visible
propriété.Juste une idée ... ça marche pour moi.
la source
DataGridView
, cela a parfaitement fonctionné. :) Bien que j'utilise unforeach
et directement assignérow.Visible = showAll || <condition>;
sans aucunif
. CelashowAll
est vrai si la chaîne de filtre est vide.Vous pouvez créer un objet DataView à partir de votre source de données. Cela vous permettrait de filtrer et de trier vos données sans modifier directement la source de données.
N'oubliez pas d'appeler
dataGridView1.DataBind();
après avoir défini la source de données.la source
// "Comment" Filtrer la grille de données sans changer l'ensemble de données, fonctionne parfaitement.
la source
J'ai une proposition plus claire sur la recherche automatique dans un DataGridView
Ceci est un exemple
la source
J'ai trouvé un moyen simple de résoudre ce problème. Lors de la liaison de datagridview, vous venez de faire:
datagridview.DataSource = dataSetName.Tables["TableName"];
Si vous codez comme:
le datagridview ne chargera plus jamais les données lors du filtrage.
la source