一尘不染

在不更改数据源的情况下过滤DataGridView

c#

我正在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 = 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:但是,它更改了数据源。所以解决方案:

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上看到的那样,这是不可接受的…

我不想这样做,因为程序员可能会编写类似于以下内容的代码:

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。代码将被编译,但是,使用过滤器后,它将引发异常。

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

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


阅读 215

收藏
2020-05-19

共1个答案

一尘不染

我在一个类似的问题上花了一个小时。对我来说,答案非常简单。

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