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.
Jawaban:
Saya hanya menghabiskan satu jam untuk masalah yang sama. Bagi saya jawabannya ternyata sangat sederhana dan memalukan.
sumber
IBindingListView
sesuai msdn.microsoft.com/en-us/library/…Object reference not set to an instance of an object.
untuk GridView.Saya mengembangkan pernyataan umum untuk menerapkan filter:
Tanda kurung siku memungkinkan adanya spasi pada nama kolom.
Selain itu, jika Anda ingin menyertakan beberapa nilai dalam filter Anda, Anda dapat menambahkan baris berikut untuk setiap nilai tambahan:
sumber
Cara yang lebih sederhana adalah dengan melintang data, dan menyembunyikan garis dengan
Visible
properti.Hanya sebuah ide ... itu berhasil untukku.
sumber
DataGridView
, ini bekerja dengan sempurna. :) Meskipun saya menggunakanforeach
dan langsung ditugaskanrow.Visible = showAll || <condition>;
tanpaif
. ItushowAll
benar jika string filter kosong.Anda bisa membuat objek DataView dari sumber data Anda. Ini akan memungkinkan Anda untuk memfilter dan menyortir data Anda tanpa mengubah sumber data secara langsung.
Selain itu, ingatlah untuk menelepon
dataGridView1.DataBind();
setelah Anda menyetel sumber data.sumber
// "Komentar" Filter datagrid tanpa mengubah dataset, bekerja dengan sempurna.
sumber
Saya memiliki proposal yang lebih jelas tentang pencarian otomatis di DataGridView
ini sebuah contoh
sumber
Saya menemukan cara sederhana untuk memperbaiki masalah itu. Di binding datagridview yang baru saja Anda lakukan:
datagridview.DataSource = dataSetName.Tables["TableName"];
Jika Anda membuat kode seperti:
datagridview tidak akan pernah memuat data lagi saat memfilter.
sumber