C # Visual Studio 2010'da kullanıcı denetimi geliştiriyorum - veri görünümüne filtre uygulamak için bir tür "hızlı bul" metin kutusu. 3 tür datagridview veri kaynağı için çalışmalıdır: DataTable, DataBinding ve DataSet. Benim sorunum DataGridView'da görüntülenen DataSet nesnesinden DataTable'ı filtrelemekle ilgili.
3 durum olabilir (üzerinde DataGridView ve TextBox bulunan standart WinForm uygulaması örnekleri) - ilk 2 çalışıyor, tamam, 3. bir ile sorunum var:
1. datagridview.DataSource = dataTable:
ayarlayarak filtreleyebileceğim şekilde çalışıyor : dataTable.DefaultView.RowFilter = "ülke GİBİ '% 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: Çalışıyor,
böylece ayarlayarak filtreleyebilirim: bindingSource.Filter = "ülke 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": çalışmıyor
Designer kullanarak bir tablo tasarladığınızda gerçekleşir: DataSet'i toolbox'tan forma koyun, dataTable'ı ekleyin ve ardından datagridview.DataSource = dataSource; ve datagridview.DataMember = "TableName".
Aşağıdaki kod, bu işlemleri varsayar:
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());
}
Test ederseniz - datatable filtrelenmiş olmasına rağmen (ds.Tables [0] .DefaultView.Count değişiklikleri), datagridview güncellenmez ... Uzun zamandır herhangi bir çözüm arıyordum, ancak sorun şu ki DataSource yapamıyor değişiklik - ek bir kontrol olduğu için, programcının kodunu karıştırmasını istemiyorum.
Olası çözümlerin şunlar olduğunu biliyorum:
- DataTable'ı DataBinding kullanarak DataSet'ten bağlamak ve örnek 2 olarak kullanmak: ancak kod yazma sırasında programcıya bağlı,
- dataSource'u BindingSource, dataGridView.DataSource = dataSet.Tables [0] veya Programlı olarak DefaultView'a: Ancak, DataSource'u değiştirir. Yani çözüm:
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());
}
MessageBox'ın dataSource'ta gördüğünüz gibi kabul edilemez ...
Bunu yapmak istemiyorum çünkü bir programcı şuna benzer bir kod yazabilir:
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
}
Bunu tasarımcıda DataSet ve DataMember ile DataGridView'i tasarladığı için yapabilir. Kod derlenecek, ancak bir filtre kullandıktan sonra bir istisna atacak ...
Öyleyse soru şu: DataSet'te DataTable'ı nasıl filtreleyebilirim ve DataSource'u diğerine değiştirmeden DataGridView'de sonuçları nasıl gösterebilirim? DataTable'ı DataSet'ten filtrelemek çalışırken neden DataTable'ı doğrudan 1. örnekten filtreleyebilirim? Belki bu durumda DataGridView'e bağlı DataTable değildir?
Lütfen sorunumun sorunları tasarlamaktan kaynaklandığını, bu nedenle çözümün Örnek 3'te ÇALIŞMALIDIR.