共用方式為


將資料繫結至控制項 (WCF 資料服務)

有了 WCF Data Services ,您可以將類似 ComboBoxListView 的控制項繫結至 DataServiceCollection 類別的執行個體。 這個集合 (繼承自 ObservableCollection 類別) 包含 Open Data Protocol (OData) 摘要中的資料。 此類別表示在加入或移除項目時提供通知的動態資料集合。 當您使用 DataServiceCollection 的執行個體進行資料繫結時,WCF Data Services 用戶端程式庫會處理這些事件,以確保 DataServiceContext 所追蹤的物件會與繫結 UI 項目中的資料保持同步。

在集合中加入或移除物件時,DataServiceCollection 類別會 (間接) 實作 INotifyCollectionChanged 介面以警示內容。 與 DataServiceCollection 搭配使用的資料服務類型物件也必須實作 INotifyPropertyChanged 介面,以便在繫結集合中的物件屬性發生變更時警示 DataServiceCollection

Ee373844.note(zh-tw,VS.100).gif注意:
當您使用 [加入服務參考] 對話或 DataSvcUtil.exe 工具搭配 /dataservicecollection 選項來產生用戶端資料服務類別時,所產生的資料類別會實作 INotifyPropertyChanged 介面。如需詳細資訊,請參閱 HOW TO:手動產生用戶端資料服務類別 (WCF Data Services)

建立繫結集合

以提供的 DataServiceContext 執行個體及選擇性的 DataServiceQuery 或 LINQ 查詢 (執行此查詢時會傳回 IEnumerable 執行個體) 呼叫其中一個類別建構函式方法,建立一個新的 DataServiceCollection 類別執行個體。 此 IEnumerable 會提供繫結集合的物件來源,這些物件是從 OData 摘要具體化而來。 如需詳細資訊,請參閱物件具體化 (WCF Data Services)。 根據預設,DataServiceContext 會自動追蹤對插入於集合中的繫結物件和項目所做的變更。 如需手動追蹤這些變更,請呼叫其中一個使用 trackingMode 參數的建構函式方法,並指定 None 的值。

下列範例示範如何根據所提供的 DataServiceContext 以及傳回所有客戶與相關訂單的 DataServiceQuery 建立 DataServiceCollection 執行個體。

' Create a new collection that contains all customers and related orders.
Dim trackedCustomers As DataServiceCollection(Of Customer) = _
        New DataServiceCollection(Of Customer)(context.Customers.Expand("Orders"))
// Create a new collection that contains all customers and related orders.
DataServiceCollection<Customer> trackedCustomers = 
    new DataServiceCollection<Customer>(context.Customers.Expand("Orders"));

繫結資料至 Windows Presentation Foundation 項目

由於 DataServiceCollection 類別繼承自 ObservableCollection 類別,因此您可以在 Windows Presentation Foundation (WPF) 應用程式中將物件繫結至項目或控制項,就像使用 ObservableCollection 類別進行繫結一樣。 如需詳細資訊,請參閱資料繫結 (Windows Presentation Foundation)。 繫結資料服務資料至 WPF 控制項的其中一個方法是將項目的 DataContext 屬性設定為包含查詢結果之 DataServiceCollection 類別的執行個體。 在這種情況下,您可以使用 ItemsSource 屬性來設定控制項的物件來源。 使用 DisplayMemberPath 屬性來指定要顯示繫結物件的哪一個屬性。 如果您要將項目繫結至導覽屬性所傳回的相關物件,請在為 ItemsSource 屬性定義的繫結中加入路徑。 這個路徑是相對於父控制項 DataContext 屬性所設定的根物件位置。 下列範例會設定 StackPanel 項目的 DataContext 屬性,將父控制項繫結至客戶物件的 DataServiceCollection

' Create a LINQ query that returns customers with related orders.
Dim customerQuery = From cust In context.Customers.Expand("Orders") _
                        Where cust.Country = customerCountry _
                        Select cust

' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery, _
        TrackingMode.AutoChangeTracking, "Customers", _
        AddressOf OnMyPropertyChanged, AddressOf OnMyCollectionChanged)

' Bind the root StackPanel element to the collection
' related object binding paths are defined in the XAML.
Me.LayoutRoot.DataContext = trackedCustomers
// Create a LINQ query that returns customers with related orders.
var customerQuery = from cust in context.Customers.Expand("Orders")
                    where cust.Country == customerCountry
                    select cust;

// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery, 
    TrackingMode.AutoChangeTracking,"Customers", 
    OnPropertyChanged, OnCollectionChanged);

// Bind the root StackPanel element to the collection;
// related object binding paths are defined in the XAML.
this.LayoutRoot.DataContext = trackedCustomers;

下列範例顯示子控制項 DataGridComboBox 的 XAML 繫結定義:

<StackPanel Orientation="Vertical" Height="Auto" Name="LayoutRoot" Width="Auto">
    <Label Content="Customer ID" Margin="20,0,0,0" />
    <ComboBox Name="customerIDComboBox" DisplayMemberPath="CustomerID" ItemsSource="{Binding}" 
              IsSynchronizedWithCurrentItem="True" SelectedIndex="0" Height="23" Width="120" 
              HorizontalAlignment="Left" Margin="20,0,0,0" VerticalAlignment="Center" />
    <ListView ItemsSource="{Binding Path=Orders}" Name="ordersDataGrid" Margin="34,46,34,50">
        <ListView.View>
            <GridView AllowsColumnReorder="False" ColumnHeaderToolTip="Line Items">
                <GridViewColumn DisplayMemberBinding="{Binding Path=OrderID, Mode=OneWay}" 
                    Header="Order ID" Width="50"/>
                <GridViewColumn DisplayMemberBinding="{Binding Path=OrderDate, Mode=TwoWay}" 
                    Header="Order Date" Width="50"/>
                <GridViewColumn DisplayMemberBinding="{Binding Path=Freight, Mode=TwoWay}" 
                    Header="Freight Cost" Width="50"/>
            </GridView>
        </ListView.View>
    </ListView>
    <Button Name="saveChangesButton" Content="Save Changes" Click="saveChangesButton_Click" 
            Width="80" Height="30" Margin="450,0,0,0"/>
</StackPanel>

如需詳細資訊,請參閱 HOW TO:將資料繫結至 Windows Presentation Foundation 項目 (WCF Data Services)

實體加入一對多或多對多關聯性時,關聯性的導覽屬性會傳回相關物件集合。 當您使用 [加入服務參考] 對話方塊或 DataSvcUtil.exe 工具產生用戶端服務類別時,導覽屬性會傳回 DataServiceCollection 的執行個體。 這樣可讓您將相關物件繫結至控制項,同時支援一般的 WPF 繫結案例,例如相關實體的主版詳細資料繫結模式。 在前述的 XAML 範例中,XAML 程式碼會將主版 DataServiceCollection 繫結至根資料項目。 接著會將訂單 DataGrid 繫結至從所選 Customers 物件傳回的 Orders DataServiceCollection,然後再繫結至 Window 的根項目。

將資料繫結至 Windows Form 控制項

若要將物件繫結至 Windows Form 控制項,請將控制項的 DataSource 屬性設定為包含查詢結果之 DataServiceCollection 類別的執行個體。

Ee373844.note(zh-tw,VS.100).gif注意:
只有接聽變更事件的控制項才支援資料繫結,透過的方式是實作 INotifyCollectionChangedINotifyPropertyChanged 介面。當控制項不支援這種變更通知時,對基礎 DataServiceCollection 所做的變更不會反映在繫結控制項中。

下列範例會將 DataServiceCollection 繫結到 ComboBox 控制項:

' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)

'Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID"
customersComboBox.DataSource = trackedCustomers
// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery);

//Bind the Customers combobox to the collection.
customersComboBox.DisplayMember = "CustomerID";
customersComboBox.DataSource = trackedCustomers;

當您使用 [加入服務參考] 對話方塊產生用戶端資料服務類別時,也會根據所產生的 DataServiceContext 建立專案資料來源。 您可以使用此資料來源建立 UI 項目或控制項,將項目從 [資料來源] 視窗拖曳至設計工具上,以顯示資料服務的資料。 這些項目會成為繫結至資料來源之應用程式 UI 中的項目。 如需詳細資訊,請參閱 HOW TO:使用專案資料來源繫結資料 (WCF Data Services)

繫結分頁資料

您可以設定資料服務來限制單一回應訊息中傳回的查詢資料量。 如需詳細資訊,請參閱設定資料服務 (WCF Data Services)。 當資料服務分頁回應資料時,每個回應都會包含一個連結以傳回下一頁結果。 如需詳細資訊,請參閱載入延後的內容 (WCF 資料服務)。 在這個情況下,您必須傳遞從 NextLinkUri 屬性取得的 URI,在 DataServiceCollection 呼叫 Load 方法,以明確地載入頁面,如下列範例所示:

    ' Create a new collection for binding based on the LINQ query.
trackedCustomers = New DataServiceCollection(Of Customer)(customerQuery)

    ' Load all pages of the response at once.
While trackedCustomers.Continuation IsNot Nothing
    trackedCustomers.Load( _
            context.Execute(Of Customer)(trackedCustomers.Continuation.NextLinkUri))
End While
// Create a new collection for binding based on the LINQ query.
trackedCustomers = new DataServiceCollection<Customer>(customerQuery);

// Load all pages of the response at once.
while (trackedCustomers.Continuation != null)
{
    trackedCustomers.Load(
        context.Execute<Customer>(trackedCustomers.Continuation.NextLinkUri));
}

相關物件會以類似的方式載入。 如需詳細資訊,請參閱 HOW TO:將資料繫結至 Windows Presentation Foundation 項目 (WCF Data Services)

自訂資料繫結行為

DataServiceCollection 類別可讓您攔截變更集合時所引發的事件,例如加入或移除物件,以及變更集合中物件的屬性時所引發的事件。 您可以修改資料繫結事件以覆寫預設的行為,包括下列條件約束:

  • 委派內未執行驗證。

  • 加入實體時會自動加入相關的實體。

  • 刪除實體時不會刪除相關的實體。

當您建立新的 DataServiceCollection 執行個體時,您可以選擇指定下列參數,這些參數會定義處理變更繫結物件時引發之事件的方法委派。

  • entityChanged:繫結物件變更時會呼叫此方法。 此 Func 委派接受 EntityChangedParams 物件並傳回布林值,指出是否仍應發生預設行為 (呼叫 DataServiceContextUpdateObject)。

  • entityCollectionChanged:在繫結集合中加入或移除物件時會呼叫此方法。 此 Func 委派接受 EntityCollectionChangedParams 物件並傳回布林值,指出是否仍應發生預設行為 (呼叫 Add 動作的 AddObject,或在 DataServiceContext 呼叫 Remove 動作的 DeleteObject)。

Ee373844.note(zh-tw,VS.100).gif注意:
WCF Data Services 不會針對您在這些委派中實作的自訂行為執行驗證。

下列範例會自訂 Remove 動作以呼叫 DeleteLinkDeleteObject 方法來移除屬於已刪除之 Orders 實體的 Orders_Details 方法。 由於刪除父實體時不會自動刪除相依實體,因此會執行這個自訂行為。

' Method that is called when the CollectionChanged event is handled.
Private Function OnMyCollectionChanged( _
    ByVal entityCollectionChangedinfo As EntityCollectionChangedParams) As Boolean
    If entityCollectionChangedinfo.Action = _
        NotifyCollectionChangedAction.Remove Then

        ' Delete the related items when an order is deleted.
        If entityCollectionChangedinfo.TargetEntity.GetType() Is GetType(Order) Then

            ' Get the context and object from the supplied parameter.
            Dim context = entityCollectionChangedinfo.Context
            Dim deletedOrder As Order = _
            CType(entityCollectionChangedinfo.TargetEntity, Order)

            If deletedOrder.Order_Details.Count = 0 Then
                ' Load the related OrderDetails.
                context.LoadProperty(deletedOrder, "Order_Details")
            End If

            ' Delete the order and its related items
            For Each item As Order_Detail In deletedOrder.Order_Details
                context.DeleteObject(item)
            Next

            ' Delete the order and then return false since the object is already deleted.
            context.DeleteObject(deletedOrder)

            Return True
        Else
            Return False
        End If
    Else
        ' Use the default behavior.
        Return False
    End If
End Function
// Method that is called when the CollectionChanged event is handled.
private bool OnCollectionChanged(
    EntityCollectionChangedParams entityCollectionChangedinfo)
{
    if (entityCollectionChangedinfo.Action ==
        NotifyCollectionChangedAction.Remove)
    {
        // Delete the related items when an order is deleted.
        if (entityCollectionChangedinfo.TargetEntity.GetType() == typeof(Order))
        {
            // Get the context and object from the supplied parameter.
            DataServiceContext context = entityCollectionChangedinfo.Context;
            Order deletedOrder = entityCollectionChangedinfo.TargetEntity as Order;

            if (deletedOrder.Order_Details.Count == 0)
            {
                // Load the related OrderDetails.
                context.LoadProperty(deletedOrder, "Order_Details");
            }

            // Delete the order and its related items;
            foreach (Order_Detail item in deletedOrder.Order_Details)
            {
                context.DeleteObject(item);
            }

            // Delete the order and then return true since the object is already deleted.
            context.DeleteObject(deletedOrder);

            return true;
        }
        else
        {
            return false;
        }
    }
    else 
    {
        // Use the default behavior.
        return false;
    }
}

如需詳細資訊,請參閱 HOW TO:自訂資料繫結行為 (WCF Data Services)

使用 Remove 方法移除 DataServiceCollection 中的物件時,預設行為是在 DataServiceContext 中將該物件也標記為已刪除。 若要變更此行為,您可以將委派指定為發生 CollectionChanged 事件時呼叫之 entityCollectionChanged 參數中的方法。

使用自訂用戶端資料類別資料繫結

若要將物件載入至 DataServiceCollection,物件本身必須實作 INotifyPropertyChanged 介面。 使用 [加入服務參考] 對話方塊或 DataSvcUtil.exe 工具實作此介面時所產生的資料服務用戶端類別。 如果您自行提供用戶端資料類別,則必須使用另一種集合類型進行資料繫結。 物件變更時,您必須在資料繫結控制項中處理事件,以呼叫 DataServiceContext 類別的下列方法:

  • AddObject:將新的物件加入至集合中時。

  • DeleteObject:自集合移除物件時。

  • UpdateObject:集合中的物件屬性變更時。

  • AddLink:將物件加入至相關物件集合中時。

  • SetLink:將物件加入至相關物件集合中時。

如需詳細資訊,請參閱更新資料服務 (WCF Data Services)

另請參閱

工作

HOW TO:手動產生用戶端資料服務類別 (WCF Data Services)
HOW TO:加入資料服務參考 (WCF Data Services)