2011-04-30 106 views
77

我正在C#Visual Studio 2010中開發用戶控件 - 一種用於過濾datagridview的「快速查找」文本框。它應該適用於3種類型的datagridview數據源:DataTable,DataBinding和DataSet。 我的問題是從DataSet對象中過濾DataTable,它顯示在DataGridView上。在不改變數據源的情況下過濾DataGridView

有可能爲3例(與DataGridView的文本框,並在其上的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 = 「國家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的不更新...... 我去過:
代碼下面假裝這些操作尋找任何解決方案很長一段時間,但問題是,數據源不能更改 - 因爲它是額外的控制,我不希望它搞亂了程序員的代碼。

我知道可能的解決方案是:
- 使用數據綁定從數據集綁定數據表,並用它作爲例子2:但是它的代碼編寫過程中是由程序員,
- 改變的數據源的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的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。 代碼將被編譯,但是,使用過濾器後,它會拋出一個異常...

所以問題是:如何過濾DataSet中的DataTable並顯示DataGridView上的結果而不更改DataSource到另一個?爲什麼我可以直接從示例1過濾DataTable,而從DataSet過濾DataTable不起作用? 也許這不是DataTable在這種情況下綁定到DataGridView?

請注意,我的問題,從設計問題的重視,因此該解決方案必須工作在例如3

+0

我除了所有寶貴的意見和方案2美分。這是一篇[文章](http://10tec.com/articles/datagridview-filter.aspx),它描述了以這種方式過濾數據綁定的DataGridView的優點和缺點,併爲您提供了一些更好的方法。 – TecMan 2015-02-19 16:35:25

+0

不要重複,但我認爲我的建議不會每次都有效。事實上,有時我們的代碼不太可能會解除例外。試着用一個bindingSource進行過濾,你有機會做出好的代碼。像日期:bindingSource.Filter = string.Format ..... – 2017-04-17 12:13:05

回答

105

我剛在一個類似的問題上花了一個小時。對我來說,答案結果令人尷尬地簡單。

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

如何把這個事件綁定到文本框 – 2016-03-18 10:23:41

+4

過濾語法可以在這裏找到:http://www.csharp-examples.net/dataview-rowfilter/ – Sal 2017-02-23 21:13:01

+0

使用DataTable作爲源解決了必須實現IBindingListView '根據https://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.filter(VS.90).aspx – 2017-12-04 02:33:37

1

您可以創建從一個數據源對象DataView。這將允許您在不直接修改數據源的情況下過濾和排序數據。

另外,請記得在設置數據源後調用dataGridView1.DataBind();

+2

謝謝你的回答。是的,可以創建DataView對象,但它會更改DataSource類型,請參閱最後一個代碼。我在之前的文章中修改了爲什麼要避免這種情況的原因。 DataGridView1.DataBind()方法在WinForms中不存在,我想它是來自ASP。 – mj82 2011-05-01 13:06:00

14

我開發了一個通用的聲明中應用濾鏡:

string rowFilter = string.Format("[{0}] = '{1}'", columnName, filterValue); 
(myDataGridView.DataSource as DataTable).DefaultView.RowFilter = rowFilter; 

的方括號允許在列名的空間。

此外,如果你想在你的過濾多個值,你可以添加以下行,每增加值:

rowFilter += string.Format(" OR [{0}] = '{1}'", columnName, additionalFilterValue); 
-1

我發現了一個簡單的方法來解決這個問題。在綁定的DataGridView你剛剛完成:datagridview.DataSource = dataSetName.Tables["TableName"];

如果這樣的代碼:

datagridview.DataSource = dataSetName; 
datagridview.DataMember = "TableName"; 

在DataGridView絕不會在過濾時再加載數據。

0

//「評論」在沒有改變數據集的情況下過濾數據網格,完美的工作。

  (dg.ItemsSource as ListCollectionView).Filter = (d) => 
      { 
       DataRow myRow = ((System.Data.DataRowView)(d)).Row; 
       if (myRow["FName"].ToString().ToUpper().Contains(searchText.ToString().ToUpper()) || myRow["LName"].ToString().ToUpper().Contains(searchText.ToString().ToUpper())) 
        return true; //if want to show in grid 
       return false; //if don't want to show in grid 
      };   
3

一個更簡單的方法是橫向於數據,是隱藏可見屬性的行。

//顯示所有線路

 for (int u = 0; u < dataGridView3.RowCount; u++) 
     { 
      dataGridView3.Rows[u].Visible = true; 
      x++; 
     } 

//隱藏你想和你想要的過濾器的人。

 for (int u = 0; u < dataGridView3.RowCount; u++) 
     { 
      if (dataGridView3.Rows[u].Cells[4].Value == "The filter string") 
      { 
       dataGridView3.Rows[u].Visible = true; 
      } 
      else 
      { 
       dataGridView3.Rows[u].Visible = false; 
      } 
     } 

只是一個想法......對於mi作品。

+0

作爲手動填充'DataGridView'的人,這個工作很完美。 :)雖然我使用了一個'foreach'並直接分配了'row.Visible = showAll || ;'沒有任何'if'。如果過濾字符串爲空,那麼'showAll'爲true。 – Andrew 2017-01-09 18:57:52

0

我在一個DataGridView

這對自動搜索更清晰的建議就是一個例子

private void searchTb_TextChanged(object sender, EventArgs e) 
    { 
     try 
     { 
      (lecteurdgview.DataSource as DataTable).DefaultView.RowFilter = String.IsNullOrEmpty(searchTb.Text) ? 
       "lename IS NOT NULL" : 
       String.Format("lename LIKE '{0}' OR lecni LIKE '{1}' OR ledatenais LIKE '{2}' OR lelieu LIKE '{3}'", searchTb.Text, searchTb.Text, searchTb.Text, searchTb.Text); 
     } 
     catch (Exception ex) { 
      MessageBox.Show(ex.StackTrace); 
     } 
    } 
+0

可能與http://stackoverflow.com/questions/5843537/filtering-datagridview-without-changing-datasource重複 – 2017-04-06 17:31:54

相關問題