Saya sedang mengembangkan kontrol pengguna di C # Visual Studio 2010 - semacam kotak teks "pencarian cepat" untuk memfilter datagridview. Ini harus bekerja untuk 3 jenis sumber data datagridview: DataTable, DataBinding dan DataSet. Masalah saya adalah dengan memfilter DataTable dari objek DataSet, yang ditampilkan di DataGridView.
Mungkin ada 3 kasus (contoh untuk aplikasi WinForm standar dengan DataGridView dan TextBox di atasnya) - 2 pertama berfungsi OK, saya bermasalah dengan yang ketiga:
1. datagridview.DataSource = dataTable: berfungsi
jadi saya bisa memfilter dengan menyetel: 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: berfungsi
sehingga saya dapat memfilter dengan menyetel: 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": tidak berfungsi
Ini terjadi saat Anda mendesain tabel menggunakan desainer: letakkan DataSet dari toolbox di formulir, tambahkan dataTable ke dalamnya, lalu setel datagridview.DataSource = dataSource; dan datagridview.DataMember = "TableName".
Kode di bawah menganggap operasi ini:
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());
}
Jika Anda mengujinya - meskipun datatable difilter (ds.Tables [0] .DefaultView.Count berubah), datagridview tidak diperbarui ... Saya sudah lama mencari solusi apa pun, tetapi masalahnya adalah bahwa DataSource tidak bisa ubah - karena ini adalah kontrol tambahan, saya tidak ingin mengacaukan kode programmer.
Saya tahu solusi yang mungkin adalah:
- untuk mengikat DataTable dari DataSet menggunakan DataBinding dan menggunakannya sebagai contoh 2: tetapi terserah programmer selama penulisan kode,
- untuk mengubah dataSource ke BindingSource, dataGridView.DataSource = dataSet.Tables [0], atau ke DefaultView secara programatik: namun, ini mengubah Sumber Data. Jadi solusinya:
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());
}
tidak dapat diterima, seperti yang Anda lihat di MessageBox's dataSource berubah ...
Saya tidak ingin melakukan itu, karena mungkin saja seorang programmer menulis kode yang mirip dengan ini:
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
}
Dia bisa melakukan itu, karena dia mendesain DataGridView dengan DataSet dan DataMember di desainer. Kode akan dikompilasi, namun, setelah menggunakan filter, itu akan memunculkan pengecualian ...
Jadi pertanyaannya adalah: bagaimana cara memfilter DataTable di DataSet dan menampilkan hasilnya di DataGridView tanpa mengubah DataSource ke yang lain? Mengapa saya dapat memfilter DataTable dari contoh 1 secara langsung, sementara memfilter DataTable dari DataSet tidak berfungsi? Mungkin itu tidak DataTable terikat ke DataGridView dalam kasus itu?
Harap dicatat, bahwa masalah saya berasal dari masalah desain, jadi solusinya HARUS BEKERJA pada contoh 3.