【发布时间】:2011-08-16 03:47:27
【问题描述】:
我正在 C# Visual Studio 2010 中开发用户控件 - 一种用于过滤 datagridview 的“快速查找”文本框。它应该适用于 3 种类型的 datagridview 数据源:DataTable、DataBinding 和 DataSet。 我的问题是从显示在 DataGridView 上的 DataSet 对象过滤 DataTable。
可能有 3 种情况(带有 DataGridView 和 TextBox 的标准 WinForm 应用程序示例)-前 2 种工作正常,我对第 3 种有问题:
1. datagridview.DataSource = dataTable :它有效
所以我可以通过设置进行过滤: 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:它有效
所以我可以通过设置进行过滤: 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 = 数据源; datagridview.DataMember = "TableName":它不起作用
当您使用设计器设计表格时会发生这种情况:将工具箱中的 DataSet 放在表单上,将 dataTable 添加到其中,然后设置 datagridview.DataSource = dataSource;和 datagridview.DataMember = "TableName"。
下面的代码假装这些操作:
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());
}
如果您对其进行测试 - 尽管数据表已被过滤(ds.Tables[0].DefaultView.Count 更改),但 datagridview 不会更新... 我一直在寻找任何解决方案,但问题是 DataSource 无法更改 - 因为它是额外的控制,我不希望它弄乱程序员的代码。
我知道可能的解决方案是:
- 使用 DataBinding 从 DataSet 绑定 DataTable 并将其用作示例 2:但在代码编写期间由程序员决定,
- 以编程方式将 dataSource 更改为 BindingSource、dataGridView.DataSource = dataSet.Tables[0] 或 DefaultView:但是,它会更改 DataSource。所以解决方案:
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 的数据源上看到的那样正在改变......
我不想这样做,因为程序员可能会编写类似这样的代码:
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
}
他可以做到这一点,因为他在设计器中使用 DataSet 和 DataMember 设计了 DataGridView。 代码会被编译,但是使用过滤器后会抛出异常...
所以问题是:如何过滤 DataSet 中的 DataTable 并在 DataGridView 上显示结果而不将 DataSource 更改为另一个?为什么我可以直接从示例 1 中过滤 DataTable,而从 DataSet 中过滤 DataTable 不起作用? 在这种情况下,也许它不是绑定到 DataGridView 的 DataTable ?
请注意,我的问题来自设计问题,因此解决方案必须适用于示例 3。
【问题讨论】:
-
我的 2 美分,以及所有有价值的 cmets 和解决方案。这是一个article,它描述了以这种方式过滤数据绑定 DataGridView 的优缺点,并为您提供了一些如何更好地做到这一点的想法。
-
请原谅重复,但我认为我的建议并非每次都有效。确实,有时会引发异常,而我的代码不太可能。尝试使用 bindingSource 进行过滤,您将有机会编写好的代码。喜欢日期:bindingSource.Filter = string.Format.....
-
我喜欢 TecMan 的评论。您可以通过 filter 属性将过滤工作委托给 IBindingListView 接口(工作较少,但仅可与 ADO.Net Datatable 一起使用)或在您的控件中完成整个工作(更多工作,但应该适用于任何事情)。
标签: c# winforms visual-studio-2010 datagridview filter