共用方式為


將資料繫結至控制項 (WCF Data Services)

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

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

注意

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

建立繫結集合

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

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

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

' 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)

    ' 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.
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 Customers)(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
    Me.LayoutRoot.UpdateLayout()
' 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;
// 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);

// Bind the root StackPanel element to the collection;
// related object binding paths are defined in the XAML.
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<T> 的執行個體。 這樣可讓您將相關物件繫結至控制項,同時支援一般的 WPF 繫結案例,例如相關實體的主版詳細資料繫結模式。 在前述的 XAML 範例中,XAML 程式碼會將主版 DataServiceCollection<T> 繫結至根資料項目。 接著會將訂單 DataGrid 繫結至從所選 Customers 物件傳回的 Orders DataServiceCollection<T>,然後再繫結至 Window 的根項目。

將資料繫結至 Windows Form 控制項

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

注意

只有接聽變更事件的控制項才支援資料繫結,透過的方式是實作 INotifyCollectionChangedINotifyPropertyChanged 介面。當控制項不支援這種變更通知時,對基礎 DataServiceCollection<T> 所做的變更不會反映在繫結控制項中。

下列範例會將 DataServiceCollection<T> 繫結到 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 Data Services)。 在這個情況下,您必須傳遞從 NextLinkUri 屬性取得的 URI,在 DataServiceCollection<T> 呼叫 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<T> 類別可讓您攔截變更集合時所引發的事件,例如加入或移除物件,以及變更集合中物件的屬性時所引發的事件。 您可以修改資料繫結事件以覆寫預設的行為,包括下列條件約束:

  • 委派內未執行驗證。

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

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

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

注意

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(Orders) Then

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

            ' Load the related OrderDetails.
            context.LoadProperty(deletedOrder, "Order_Details")

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

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

            Return False
        Else
            Return True
        End If
    Else
        ' Use the default behavior.
        Return True
    End If
End Function
' 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<T> 中的物件時,預設行為是在 DataServiceContext 中將該物件也標記為已刪除。 若要變更此行為,您可以將委派指定為發生 CollectionChanged 事件時呼叫之 entityCollectionChanged 參數中的方法。

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

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

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

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

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

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

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

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

請參閱

工作

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

HOW TO:加入資料服務參考 (WCF Data Services)