使用特定準則篩選數據,然後透過UI控制項將數據呈現給用戶端的能力,是數據系結的重要層面。 DataView 提供數種方式來篩選數據,並傳回符合特定篩選準則的數據列子集。 除了以字串為基礎的篩選功能之外, DataView 也提供使用 LINQ 運算式進行篩選準則的功能。 LINQ 運算式允許比字串型篩選更複雜且強大的篩選作業。
使用 篩選資料 DataView的方法有兩種:
使用篩選條件從查詢生成 DataView
DataView物件可以從LINQ to DataSet查詢建立。 如果查詢包含 Where
子句, DataView 則會使用來自查詢的篩選資訊來建立 。 子句中的 Where
表達式可用來判斷哪些數據行將包含在 DataView 中,並且是篩選條件的基礎。
以表達式為基礎的篩選比更簡單的字串型篩選提供更強大且複雜的篩選。 字串型和表達式型篩選條件互斥。 當從查詢建立 RowFilter 之後設定字串型 DataView 時,會清除從查詢推斷的表達式型篩選。
備註
在大部分情況下,用於篩選的表達式不應該有副作用,而且必須具決定性。 此外,表達式不應包含任何相依於一組執行數目的邏輯,因為篩選作業可能會執行任何次數。
範例
下列範例會查詢 SalesOrderDetail 數據表裡數量大於 2 且小於 6 的訂單;從該查詢建立 DataView,並將 DataView 綁定至 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
範例
下列範例會從查詢訂單(下單日期在 2001 年 6 月 6 日之後)中建立一個 DataView 。
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
範例
篩選也可以與排序結合。 下列範例會從姓氏開頭為「S」的聯絡人查詢中建立DataView,並先依姓氏排序,再依名字排序。
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()
範例
下列範例會使用 SoundEx 演演算法來尋找姓氏類似於 「Zhu」 的連絡人。 SoundEx 演算法是在 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 是一種語音演算法,用來依聲音編製名稱的索引,因為它們以英文發音,最初由美國人口普查局開發。 SoundEx 方法會傳回名稱的四個字元代碼,其中包含英文字母,後面接著三個數位。 字母是名稱的第一個字母,而數位會編碼名稱中的其餘同音。 類似的音效名稱會共用相同的 SoundEx 程式代碼。 上一個範例之 SoundEx 方法中使用的 SoundEx 實作如下所示:
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
使用 RowFilter 屬性
的現有字串型篩選功能 DataView 仍可在 LINQ to DataSet 內容中運作。 如需字串型 RowFilter 篩選的詳細資訊,請參閱 排序和篩選數據。
下列範例會從 Contact 資料表建立 DataView,然後設定 RowFilter 屬性以傳回聯絡人姓氏為 "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 從 DataTable 或 LINQ to DataSet 查詢建立之後,您可以使用 RowFilter 方法根據其數據列值來指定數據列的子集。 字串型和表達式型篩選條件互斥。 RowFilter設定 屬性會清除從 LINQ to DataSet 查詢推斷的篩選表示式,而且無法重設篩選表達式。
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'"
如果您想要傳回數據上特定查詢的結果,而不是提供數據子集的動態檢視,您可以使用 Find 的FindRows或 DataView 方法,而不是設定 RowFilter 屬性。 屬性 RowFilter 最適合用於系結控件顯示篩選結果的數據綁定應用程式中。 設定RowFilter屬性會重建資料索引,這將增加您的應用程式的額外負荷並降低效能。 Find和 FindRows 方法會使用目前的索引,而不需要重建索引。 如果您只打算呼叫一次Find或FindRows,那麼您應該使用現有的DataView。 如果您要呼叫 Find 或 FindRows 多次,您應該建立新的 DataView 來重建您要搜尋之數據行上的索引,然後呼叫 Find 或 FindRows 方法。 如需Find 和 FindRows 方法的詳細資訊,請參閱尋找資料列和資料檢視效能。
清除篩選
DataView上的篩選器可以在使用RowFilter屬性設定篩選之後被清除。 在 DataView 上的濾器可以透過兩種不同的方式清除:
範例
下列範例會從查詢建立 DataView ,然後將 屬性設定 RowFilter 為 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
範例
下列範例會從數據表建立 DataView,先設定 RowFilter 屬性,再透過將 RowFilter 屬性設定為空字串來清除篩選。
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 = ""