it-swarm.com.de

Filtern von DataGridView ohne Änderung der Datenquelle

Ich entwickle die Benutzersteuerung in C # Visual Studio 2010 - eine Art "Quick Find" -Textfeld zum Filtern von Datagridview. Es sollte für drei Arten von Datenquellen-Datenquellen funktionieren: DataTable, DataBinding und DataSet . Mein Problem ist das Filtern von DataTable aus dem DataSet-Objekt, das in DataGridView angezeigt wird.

Es kann 3 Fälle geben (Beispiele für WinForm-Standardanwendung mit DataGridView und TextBox) - die ersten 2 funktionieren in Ordnung, ich habe ein Problem mit der dritten:

1. datagridview.DataSource = dataTable: es funktioniert
Ich kann also filtern, indem ich Folgendes setze: 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: es funktioniert
Ich kann also filtern, indem Sie Folgendes festlegen: 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": es funktioniert nicht
Dies geschieht, wenn Sie eine Tabelle mit Designer entwerfen: Legen Sie das DataSet aus der Toolbox in das Formular, fügen Sie ihm dataTable hinzu und setzen Sie dann datagridview.DataSource = dataSource; und datagridview.DataMember = "TableName".
Der folgende Code gibt die folgenden Vorgänge vor: 

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());
}

Wenn Sie es testen - obwohl datatable gefiltert wird (ds.Tables [0] .DefaultView.Count ändert sich), wird datagridview nicht aktualisiert ....... Ich habe lange nach einer Lösung gesucht, aber das Problem ist dass DataSource nicht geändert werden kann - da es zusätzliche Kontrolle gibt, möchte ich nicht, dass es mit dem Code des Programmierers durcheinander kommt. 

Ich weiß, mögliche Lösungen sind:
- um DataTable mithilfe von DataBinding aus DataSet zu binden und als Beispiel 2 zu verwenden: Es liegt jedoch beim Programmierer beim Schreiben des Codes.
-, um dataSource in BindingSource, dataGridView.DataSource = dataSet.Tables [0] oder programmgesteuert in DefaultView zu ändern: Die DataSource wird jedoch geändert. Also die Lösung: 

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());
}

ist nicht akzeptabel, wie Sie auf MessageBox's dataSource sehen, ändert sich ... 

Ich möchte das nicht tun, weil es möglich ist, dass ein Programmierer folgenden Code schreibt:

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
}

Er kann dies tun, da er DataGridView mit DataSet und DataMember in Designer entworfen hat. Der Code wird kompiliert. Nach der Verwendung eines Filters wird jedoch eine Ausnahme ausgelöst ...

Die Frage ist also: Wie kann ich DataTable in DataSet filtern und die Ergebnisse in DataGridView anzeigen, ohne DataSource in eine andere zu ändern? Warum kann ich DataTable direkt aus Beispiel 1 filtern, während das Filtern von DataTable aus DataSet nicht funktioniert? Vielleicht ist in diesem Fall keine DataTable an DataGridView gebunden? 

Bitte beachten Sie, dass mein Problem vom Entwerfen von Problemen abhängt, daher MUSS die Lösung an Beispiel 3 funktionieren. 

84
mj82

Ich habe gerade eine Stunde mit einem ähnlichen Problem verbracht. Für mich war die Antwort peinlich einfach.

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

Ich habe eine generische Anweisung entwickelt, um den Filter anzuwenden:

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

Die eckigen Klammern erlauben Leerzeichen im Spaltennamen.

Wenn Sie mehrere Werte in Ihren Filter aufnehmen möchten, können Sie außerdem die folgende Zeile für jeden zusätzlichen Wert hinzufügen:

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

Eine einfachere Methode besteht darin, die Daten zu durchqueren und die Zeilen mit der Eigenschaft Visible auszublenden.

// 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();

Nur eine Idee ... es funktioniert für mich.

5
João Moreira

Sie können ein DataView -Objekt aus Ihrer Datenquelle erstellen. Auf diese Weise können Sie Ihre Daten filtern und sortieren, ohne die Datenquelle direkt zu ändern.

Denken Sie auch daran, nach dem Festlegen der Datenquelle dataGridView1.DataBind(); aufzurufen.

1
epotter

Ich habe einen klareren Vorschlag zur automatischen Suche in einer DataGridView

dies ist ein Beispiel

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
KOUAKEP ARNOLD

// "Kommentar" Filtern Sie das Datagrid, ohne den Datensatz zu ändern. Funktioniert perfekt.

            (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
            };         
0
SPr