在不更改数据源的情况下过滤 DataGridView [英] Filtering DataGridView without changing datasource

查看:29
本文介绍了在不更改数据源的情况下过滤 DataGridView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 C# Visual Studio 2010 中开发用户控件 - 一种用于过滤 datagridview 的快速查找"文本框.它应该适用于 3 种类型的 datagridview 数据源:DataTable、DataBinding 和 DataSet.我的问题是从 DataSet 对象中过滤 DataTable,该对象显示在 DataGridView 上.

I'm developing user control in C# Visual Studio 2010 - a kind of "quick find" textbox for filtering datagridview. It should work for 3 types of datagridview datasources: DataTable, DataBinding and DataSet. My problem is with filtering DataTable from DataSet object, which is displayed on DataGridView.

可能有 3 种情况(带有 DataGridView 和 TextBox 的标准 WinForm 应用程序示例)- 前 2 种工作正常,第三种情况有问题:

There could be 3 cases (examples for standard WinForm application with DataGridView and TextBox on it) - first 2 are working OK, I've problem with 3rd one:

1.datagridview.DataSource = dataTable :它有效
所以我可以通过设置进行过滤: dataTable.DefaultView.RowFilter = "country LIKE '%s%'";

1. datagridview.DataSource = dataTable : it works
so I can filter by setting: 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%'";

2. datagridview.DataSource = bindingSource: it works
so I can filter by setting: 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":它不起作用
当您使用设计器设计表格时会发生这种情况:将工具箱中的数据集放在表单上,​​向其中添加数据表,然后设置 datagridview.DataSource = dataSource;和 datagridview.DataMember = "TableName".
下面的代码假装这些操作:

3. datagridview.DataSource = dataSource; datagridview.DataMember = "TableName": it doesn't work
It happens when you design a table using designer: put the DataSet from toolbox on form, add dataTable to it and then set datagridview.DataSource = dataSource; and datagridview.DataMember = "TableName".
Code below pretends these operations:

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 改变),数据网格视图没有更新......我一直在寻找任何解决方案,但问题是 DataSource 无法更改 - 因为它是额外的控制,我不希望它与程序员的代码混淆.

If you test it - although datatable is filtered (ds.Tables[0].DefaultView.Count changes), datagridview is not updated... I've been looking for a long time for any solution, but the problem is that DataSource cannot change - as it's additional control, I don't want it to mess up with programmer's code.

我知道可能的解决方案是:
- 使用 DataBinding 从 DataSet 绑定 DataTable 并将其用作示例 2:但在代码编写过程中取决于程序员,
- 以编程方式将 dataSource 更改为 BindingSource、dataGridView.DataSource = dataSet.Tables[0] 或 DefaultView:但是,它更改了 DataSource.所以解决方案:

I know possible solutions are:
- to bind DataTable from DataSet using DataBinding and use it as example 2: but it's up to the programmer during code writing,
- to change dataSource to BindingSource, dataGridView.DataSource = dataSet.Tables[0], or to DefaultView programatically: however, it changes the DataSource. So the solution:

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 的 dataSource 上看到的那样正在更改...

is not acceptable, as you see on MessageBox's dataSource is changing...

我不想那样做,因为程序员可能会编写类似这样的代码:

I don't want to do that, because it's possible a programmer writes code similar to this:

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.代码会被编译,但是,使用过滤器后,它会抛出异常...

He can do that, as he designed DataGridView with DataSet and DataMember in designer. Code will be compiled, however, after using a filter, it will throw an exception...

所以问题是:如何过滤DataSet 中的DataTable 并在DataGridView 上显示结果而不将DataSource 更改为另一个?为什么我可以直接从示例 1 中过滤 DataTable,而从 DataSet 中过滤 DataTable 不起作用?在这种情况下,也许不是 DataTable 绑定到 DataGridView?

So the question is: how can I filter DataTable in DataSet and show the results on DataGridView without changing DataSource to another? Why I can filter DataTable from example 1 directly, while filtering DataTable from DataSet is not working? Maybe it's not DataTable bound to DataGridView in that case?

请注意,我的问题来自设计问题,因此解决方案必须适用于示例 3.

Please note, that my problem takes from designing issues, so the solution MUST WORK on example 3.

推荐答案

我刚刚花了一个小时解决类似的问题.对我来说,答案非常简单.

I just spent an hour on a similar problem. For me the answer turned out to be embarrassingly simple.

(dataGridViewFields.DataSource as DataTable).DefaultView.RowFilter = string.Format("Field = '{0}'", textBoxFilter.Text);

这篇关于在不更改数据源的情况下过滤 DataGridView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆