Sdílet prostřednictvím


Filtrování pomocí DataView (LINQ to DataSet)

Schopnost filtrovat data pomocí konkrétních kritérií a pak je prezentovat klientovi prostřednictvím ovládacího prvku uživatelského rozhraní, je důležitým aspektem datové vazby. DataView nabízí několik způsobů filtrování dat a vrácení podmnožina řádků dat splňujících konkrétní kritéria filtru. Kromě možností filtrování založeného na řetězcích DataView poskytuje také možnost používat výrazy LINQ pro kritéria filtrování. Výrazy LINQ umožňují mnohem složitější a výkonnější operace filtrování než filtrování založené na řetězcích.

Data můžete filtrovat dvěma způsoby pomocí DataView:

  • Vytvořte DataView z dotazu LINQ to DataSet pomocí klauzule Where.

  • Použijte existující funkce filtrování založené na řetězcích DataView.

Vytvoření zobrazení dat z dotazu s informacemi o filtrování

Objekt DataView lze vytvořit z dotazu LINQ to DataSet. Pokud tento dotaz obsahuje Where klauzuli, DataView vytvoří se s informacemi o filtrování z dotazu. Výraz v Where klauzuli slouží k určení, které datové řádky budou zahrnuty do DataViewa je základem filtru.

Filtry založené na výrazech nabízejí výkonnější a složitější filtrování než jednodušší filtry založené na řetězcích. Filtry založené na řetězcích a výrazech se vzájemně vylučují. Pokud je řetězec nastaven RowFilter po DataView vytvoření z dotazu, filtr založený na výrazu odvozený z dotazu se vymaže.

Poznámka:

Ve většině případů by výrazy použité pro filtrování neměly mít vedlejší účinky a musí být deterministické. Výrazy by také neměly obsahovat žádnou logiku, která závisí na nastaveném počtu spuštění, protože operace filtrování se můžou spustit libovolný počet.

Příklad

Následující příklad dotazuje tabulku SalesOrderDetail pro objednávky s množstvím větším než 2 a menší než 6; DataView vytvoří z daného dotazu vazbu DataView na BindingSource:

DataTable orders = _dataSet.Tables["SalesOrderDetail"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<short>("OrderQty") > 2 && order.Field<short>("OrderQty") < 6
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
Dim orders As DataTable = dataSet.Tables("SalesOrderDetail")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of Int16)("OrderQty") > 2 And _
          order.Field(Of Int16)("OrderQty") < 6 _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

Příklad

Následující příklad vytvoří DataView z dotazu pro objednávky zadané po 6. červnu 2001:

DataTable orders = _dataSet.Tables["SalesOrderHeader"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<DateTime>("OrderDate") > new DateTime(2002, 6, 1)
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
Dim orders As DataTable = dataSet.Tables("SalesOrderHeader")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2002, 6, 1) _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

Příklad

Filtrování lze také kombinovat s řazením. Následující příklad vytvoří DataView z dotazu pro kontakty, jejichž příjmení začíná na "S" a seřazené podle příjmení, a pak jméno:

DataTable contacts = _dataSet.Tables["Contact"];

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where contact.Field<string>("LastName").StartsWith("S")
                                         orderby contact.Field<string>("LastName"), contact.Field<string>("FirstName")
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

Dim contacts As DataTable = dataSet.Tables("Contact")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where contact.Field(Of String)("LastName").StartsWith("S") _
    Order By contact.Field(Of String)("LastName"), contact.Field(Of String)("FirstName") _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

Příklad

Následující příklad používá algoritmus SoundEx k vyhledání kontaktů, jejichž příjmení je podobné "Zhu". Algoritmus SoundEx je implementován v metodě SoundEx.

DataTable contacts = _dataSet.Tables["Contact"];

var soundExCode = SoundEx("Zhu");

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where SoundEx(contact.Field<string>("LastName")) == soundExCode
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
Dim contacts As DataTable = dataSet.Tables("Contact")
Dim soundExCode As String = SoundEx("Zhu")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where SoundEx(contact.Field(Of String)("LastName")) = soundExCode _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

SoundEx je fonetický algoritmus používaný pro indexování názvů podle zvuku, protože jsou vyslovovány v angličtině, původně vyvinuté úřadem pro sčítání lidu USA. Metoda SoundEx vrátí čtyřmístný kód pro název skládající se z anglického písmena následovaného třemi čísly. Písmeno je první písmeno jména a čísla kódují zbývající souhlásky v názvu. Podobné názvy zvuku sdílejí stejný kód SoundEx. Zde je znázorněna implementace SoundEx použitá v metodě SoundEx předchozího příkladu:

static string SoundEx(string word)
{
    // The length of the returned code.
    const int length = 4;

    // Value to return.
    var value = "";

    // The size of the word to process.
    var size = word.Length;

    // The word must be at least two characters in length.
    if (size > 1)
    {
        // Convert the word to uppercase characters.
        word = word.ToUpper(CultureInfo.InvariantCulture);

        // Convert the word to a character array.
        var chars = word.ToCharArray();

        // Buffer to hold the character codes.
        var buffer = new StringBuilder
        {
            Length = 0
        };

        // The current and previous character codes.
        var prevCode = 0;
        var currCode = 0;

        // Add the first character to the buffer.
        buffer.Append(chars[0]);

        // Loop through all the characters and convert them to the proper character code.
        for (var i = 1; i < size; i++)
        {
            switch (chars[i])
            {
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':
                case 'H':
                case 'W':
                case 'Y':
                    currCode = 0;
                    break;
                case 'B':
                case 'F':
                case 'P':
                case 'V':
                    currCode = 1;
                    break;
                case 'C':
                case 'G':
                case 'J':
                case 'K':
                case 'Q':
                case 'S':
                case 'X':
                case 'Z':
                    currCode = 2;
                    break;
                case 'D':
                case 'T':
                    currCode = 3;
                    break;
                case 'L':
                    currCode = 4;
                    break;
                case 'M':
                case 'N':
                    currCode = 5;
                    break;
                case 'R':
                    currCode = 6;
                    break;
            }

            // Check if the current code is the same as the previous code.
            if (currCode != prevCode)
            {
                // Check to see if the current code is 0 (a vowel); do not process vowels.
                if (currCode != 0)
                {
                    buffer.Append(currCode);
                }
            }
            // Set the previous character code.
            prevCode = currCode;

            // If the buffer size meets the length limit, exit the loop.
            if (buffer.Length == length)
            {
                break;
            }
        }
        // Pad the buffer, if required.
        size = buffer.Length;
        if (size < length)
        {
            buffer.Append('0', length - size);
        }

        // Set the value to return.
        value = buffer.ToString();
    }
    // Return the value.
    return value;
}
Private Function SoundEx(ByVal word As String) As String

    Dim length As Integer = 4
    ' Value to return
    Dim value As String = ""
    ' Size of the word to process
    Dim size As Integer = word.Length
    ' Make sure the word is at least two characters in length
    If (size > 1) Then
        ' Convert the word to all uppercase
        word = word.ToUpper(System.Globalization.CultureInfo.InvariantCulture)
        ' Convert the word to character array for faster processing
        Dim chars As Char() = word.ToCharArray()
        ' Buffer to build up with character codes
        Dim buffer As StringBuilder = New StringBuilder()
        ' The current and previous character codes
        Dim prevCode As Integer = 0
        Dim currCode As Integer = 0
        ' Append the first character to the buffer
        buffer.Append(chars(0))
        ' Loop through all the characters and convert them to the proper character code
        For i As Integer = 1 To size - 1
            Select Case chars(i)

                Case "A", "E", "I", "O", "U", "H", "W", "Y"
                    currCode = 0

                Case "B", "F", "P", "V"
                    currCode = 1

                Case "C", "G", "J", "K", "Q", "S", "X", "Z"
                    currCode = 2

                Case "D", "T"
                    currCode = 3

                Case "L"
                    currCode = 4

                Case "M", "N"
                    currCode = 5

                Case "R"
                    currCode = 6
            End Select

            ' Check to see if the current code is the same as the last one
            If (currCode <> prevCode) Then

                ' Check to see if the current code is 0 (a vowel); do not process vowels
                If (currCode <> 0) Then
                    buffer.Append(currCode)
                End If
            End If
            ' Set the new previous character code
            prevCode = currCode
            ' If the buffer size meets the length limit, then exit the loop
            If (buffer.Length = length) Then
                Exit For
            End If
        Next
        ' Pad the buffer, if required
        size = buffer.Length
        If (size < length) Then
            buffer.Append("0", (length - size))
        End If
        ' Set the value to return
        value = buffer.ToString()
    End If
    ' Return the value
    Return value
End Function

Použití vlastnosti RowFilter

Stávající funkce filtrování založené na řetězcích DataView stále funguje v kontextu LINQ to DataSet. Další informace o filtrování založeném na RowFilter řetězcích najdete v tématu Řazení a filtrování dat.

Následující příklad vytvoří DataView z tabulky Kontakt a pak nastaví RowFilter vlastnost na vrácení řádků, kde je příjmení kontaktu "Zhu":

DataTable contacts = _dataSet.Tables["Contact"];

DataView view = contacts.AsDataView();

view.RowFilter = "LastName='Zhu'";

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim view As DataView = contacts.AsDataView()
view.RowFilter = "LastName='Zhu'"
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

DataView Po vytvoření dotazu LINQ DataTable to DataSet můžete pomocí RowFilter vlastnosti zadat podmnožinu řádků na základě jejich hodnot sloupců. Filtry založené na řetězcích a výrazech se vzájemně vylučují. Nastavení vlastnosti vymaže RowFilter výraz filtru odvozený z dotazu LINQ to DataSet a výraz filtru nelze obnovit.

DataTable contacts = _dataSet.Tables["Contact"];

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where contact.Field<string>("LastName") == "Hernandez"
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

view.RowFilter = "LastName='Zhu'";
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where contact.Field(Of String)("LastName") = "Hernandez" _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

dataGridView1.AutoResizeColumns()
view.RowFilter = "LastName='Zhu'"

Pokud chcete vrátit výsledky konkrétního dotazu na data, na rozdíl od poskytnutí dynamického zobrazení podmnožinu dat, můžete místo nastavení RowFilter vlastnosti použít Find metody nebo FindRows metodyDataView. Vlastnost RowFilter se nejlépe používá v aplikaci vázané na data, kde vázaný ovládací prvek zobrazuje filtrované výsledky. RowFilter Nastavení vlastnosti znovu sestaví index dat, přidá režii vaší aplikace a sníží výkon. Tyto Find metody FindRows používají aktuální index bez nutnosti znovu vytvořit index. Pokud budete volat Find nebo FindRows jen jednou, měli byste použít stávající DataView. Pokud budete volat Find nebo FindRows vícekrát, měli byste vytvořit nový DataView , který znovu sestaví index ve sloupci, který chcete vyhledat, a potom volat Find nebo FindRows metody. Další informaceoch FindFindRows

Vymazání filtru

Filtr na objektu DataView lze vymazat po nastavení filtrování pomocí RowFilter vlastnosti. Filtr na jednotce DataView lze vymazat dvěma různými způsoby:

  • Nastavte vlastnost RowFilter na null.

  • RowFilter Nastavte vlastnost na prázdný řetězec.

Příklad

Následující příklad vytvoří DataView z dotazu a potom vymaže filtr nastavením RowFilter vlastnosti na null:

DataTable orders = _dataSet.Tables["SalesOrderHeader"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<DateTime>("OrderDate") > new DateTime(2002, 11, 20)
                                            && order.Field<decimal>("TotalDue") < new decimal(60.00)
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;

view.RowFilter = null;
Dim orders As DataTable = dataSet.Tables("SalesOrderHeader")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2002, 11, 20) _
        And order.Field(Of Decimal)("TotalDue") < New Decimal(60.0) _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
view.RowFilter = Nothing

Příklad

Následující příklad vytvoří DataView z tabulky nastaví RowFilter vlastnost a potom vymaže filtr nastavením RowFilter vlastnosti na prázdný řetězec:

DataTable contacts = _dataSet.Tables["Contact"];

DataView view = contacts.AsDataView();

view.RowFilter = "LastName='Zhu'";

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

// Clear the row filter.
view.RowFilter = "";
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim view As DataView = contacts.AsDataView()
view.RowFilter = "LastName='Zhu'"
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

' Clear the row filter.
view.RowFilter = ""

Viz také