私は、C#Visual Studio 2010でユーザーコントロールを開発しています。これは、datagridviewをフィルタリングするための一種の「クイック検索」テキストボックスです。 3つのタイプのdatagridviewデータソースで動作するはずです:DataTable、DataBinding、およびDataSet。私の問題は、DataGridViewに表示されるDataSetオブジェクトからDataTableをフィルタリングすることです。
3つの場合があります(DataGridViewとTextBoxを含む標準のWinFormアプリケーションの例)-最初の2つは問題なく動作し、3つ目の問題があります:
1。datagridview.DataSource = dataTable:it works
したがって、次の設定でフィルタリングできます: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:it works
次のように設定してフィルタリングできます: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());
}
。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に変更します。ただし、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に結果を表示するにはどうすればよいですか。例1のDataTableを直接フィルタリングできるのに、DataSetのDataTableをフィルタリングできないのはなぜですか?その場合、DataGridViewにバインドされたDataTableではないのでしょうか?
私の問題は問題の設計から取っているため、ソリューションは例3で機能する必要があることに注意してください。
同様の問題に1時間を費やしました。私にとって、答えは恥ずかしいほど単純であることがわかりました。
(dataGridViewFields.DataSource as DataTable).DefaultView.RowFilter = string.Format("Field = '{0}'", textBoxFilter.Text);
フィルターを適用する一般的なステートメントを作成しました。
string rowFilter = string.Format("[{0}] = '{1}'", columnName, filterValue);
(myDataGridView.DataSource as DataTable).DefaultView.RowFilter = rowFilter;
角括弧では、列名にスペースを使用できます。
さらに、フィルターに複数の値を含める場合は、追加の値ごとに次の行を追加できます。
rowFilter += string.Format(" OR [{0}] = '{1}'", columnName, additionalFilterValue);
より簡単な方法は、データを横断し、Visible
プロパティで行を非表示にすることです。
// Prevent exception when hiding rows out of view
CurrencyManager currencyManager = (CurrencyManager)BindingContext[dataGridView3.DataSource];
currencyManager.SuspendBinding();
// Show all lines
for (int u = 0; u < dataGridView3.RowCount; u++)
{
dataGridView3.Rows[u].Visible = true;
x++;
}
// Hide the ones that you want with the filter you want.
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;
}
}
// Resume data grid view binding
currencyManager.ResumeBinding();
ただのアイデア...それは私のために働く。
データソースから DataView オブジェクトを作成できます。これにより、データソースを直接変更せずにデータをフィルタリングおよびソートできます。
また、データソースを設定した後にdataGridView1.DataBind();
を呼び出すことを忘れないでください。
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);
}
}
//「コメント」データセットを変更せずにデータグリッドをフィルタリングし、完全に機能します。
(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
};