Tôi đang phát triển quyền kiểm soát người dùng trong C # Visual Studio 2010 - một loại hộp văn bản "tìm nhanh" để lọc chế độ xem dữ liệu. Nó sẽ hoạt động cho 3 loại nguồn dữ liệu datagridview: DataTable, DataBinding và DataSet. Vấn đề của tôi là lọc DataTable từ đối tượng DataSet, được hiển thị trên DataGridView.
Có thể có 3 trường hợp (ví dụ cho ứng dụng WinForm tiêu chuẩn với DataGridView và TextBox trên đó) - 2 trường hợp đầu tiên đang hoạt động OK, tôi gặp sự cố với trường hợp thứ 3:
1. datagridview.DataSource = dataTable: nó hoạt động
để tôi có thể lọc bằng cách thiết lập: 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 = bindSource: nó hoạt động
để tôi có thể lọc bằng cách thiết lập: bindSource.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": nó không hoạt động
Điều này xảy ra khi bạn thiết kế một bảng bằng trình thiết kế: đặt DataSet từ hộp công cụ trên biểu mẫu, thêm dataTable vào nó và sau đó đặt datagridview.DataSource = dataSource; và datagridview.DataMember = "TableName".
Mã dưới đây giả vờ các hoạt động này:
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());
}
Nếu bạn kiểm tra nó - mặc dù dữ liệu được lọc (ds.Tables [0] .DefaultView.Count thay đổi), datagridview không được cập nhật ... Tôi đã tìm kiếm giải pháp trong một thời gian dài, nhưng vấn đề là DataSource không thể thay đổi - vì đó là quyền kiểm soát bổ sung, tôi không muốn nó làm xáo trộn mã của lập trình viên.
Tôi biết các giải pháp khả thi là:
- liên kết DataTable từ DataSet bằng DataBinding và sử dụng nó như ví dụ 2: nhưng tùy thuộc vào lập trình viên trong quá trình viết mã,
- thay đổi dataSource thành BindingSource, dataGridView.DataSource = dataSet.Tables [0], hoặc thành DefaultView theo chương trình: tuy nhiên, nó thay đổi DataSource. Vì vậy, giải pháp:
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());
}
là không thể chấp nhận được, như bạn thấy trên dataSource của MessageBox đang thay đổi ...
Tôi không muốn làm điều đó, vì có thể một lập trình viên viết mã tương tự như thế này:
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
}
Anh ấy có thể làm điều đó, khi anh ấy thiết kế DataGridView với DataSet và DataMember trong trình thiết kế. Mã sẽ được biên dịch, tuy nhiên, sau khi sử dụng bộ lọc, nó sẽ ném ra một ngoại lệ ...
Vì vậy, câu hỏi đặt ra là: làm thế nào tôi có thể lọc DataTable trong DataSet và hiển thị kết quả trên DataGridView mà không thay đổi DataSource thành một nguồn khác? Tại sao tôi có thể lọc DataTable từ ví dụ 1 trực tiếp, trong khi lọc DataTable từ DataSet không hoạt động? Có thể nó không phải DataTable bị ràng buộc với DataGridView trong trường hợp đó?
Xin lưu ý rằng vấn đề của tôi lấy từ vấn đề thiết kế, vì vậy giải pháp PHẢI LÀM VIỆC ở ví dụ 3.