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.