Я розробляю управління користувачами в C # Visual Studio 2010 - своєрідне текстове поле "швидкого пошуку" для фільтрації datagridview. Він повинен працювати для 3 типів джерел даних datagridview: DataTable, DataBinding та DataSet. Моя проблема полягає у фільтруванні DataTable від об'єкта DataSet, який відображається на DataGridView.
Може бути 3 випадки (приклади для стандартного додатку WinForm з DataGridView та TextBox) - перші 2 працюють нормально, у мене проблема з 3-м:
1. datagridview.DataSource = dataTable: він працює,
тому я можу фільтрувати, встановивши: dataTable.DefaultView.RowFilter = "країна ПОДОБАЄТЬСЯ '% 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 = "Ім'я
таблиці ": це не працює. Це трапляється, коли ви проектуєте таблицю за допомогою конструктора: помістіть набір даних з набору інструментів у форму, додайте до неї dataTable, а потім встановіть datagridview.DataSource = dataSource; та datagridview.DataMember = "Ім'я таблиці".
Наведений нижче код видає такі операції:
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 не може зміна - оскільки це додатковий контроль, я не хочу, щоб він псував код програміста.
Я знаю, що можливі рішення:
- пов’язати DataTable з DataSet за допомогою DataBinding і використовувати його як приклад 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());
}
неприйнятно, як ви бачите в DataBox 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
}
Він може це зробити, оскільки розробив DataGridView за допомогою DataSet та DataMember у дизайнері. Код буде скомпільовано, однак після використання фільтра він видасть виняток ...
Отже, питання полягає в тому: як я можу фільтрувати DataTable у DataSet і показувати результати на DataGridView, не змінюючи DataSource на інший? Чому я можу відфільтрувати DataTable з прикладу 1 безпосередньо, тоді як фільтрування DataTable з DataSet не працює? Може, в такому випадку це не DataTable, прив’язаний до DataGridView?
Зверніть увагу, що моя проблема береться від проектування, тому рішення МОЖЕ РОБОТИ на прикладі 3.