程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 數據點:使用 Silverlight 2 和 WCF 構建服務驅動的應用程序

數據點:使用 Silverlight 2 和 WCF 構建服務驅動的應用程序

編輯:關於.NET

本專欄基於 Silverlight 2 的 Beta 2 版本。文中的所有信息均有可能發生變更。

目錄

示例應用程序

跨域通信

Silverlight 客戶端

綁定產品列表

異步通信

產品詳細信息和綁定模式

更改事件

結束語

毋庸置疑,Silverlight™ 2 使得利用大量圖形處理技術構建豐富 Internet 應用程序 (RIA) 變得非常容易。但另一方面,Silverlight 2 可以輕松構建相當專業的業務線 (LOB) 應用程序也是不爭的事實。Silverlight 2 支持已啟用了 Windows® Presentation Foundation (WPF) 的功能強大且基於 XAML 的數據綁定子集。Silverlight 2 中的 XAML 綁定標記擴展簡化了將實體綁定到 Silverlight 控件的過程。由於它們完全在客戶端計算機上運行,因此 Silverlight 應用程序與通過服務器管理的實體是相互隔離的。這樣一來,那些通過 RSS、具象狀態傳輸 (REST) 以及 Windows Communication Foundation (WCF) 等技術實現的基於服務的通信必須是可供使用的。幸運的是,Silverlight 2 支持與這些技術和其他通信途徑的交互,這使得 Silverlight 應用程序可以與後端 LOB 應用程序無縫交互。

我將演示如何構建 Silverlight 2 UI,以使其通過與 WCF 的通信實現與業務實體和數據庫的交互。對於業務邏輯、實體模型和數據映射代碼,任何表現層都可以使用它們。我會創建將由 Silverlight 2 應用程序使用的 WCF 服務,並建立托管 WCF 服務的服務器以允許跨域調用。請注意,您可以從《MSDN® 雜志》網站下載這些示例。

示例應用程序

在開始編寫代碼之前,我們先深入了解一下此示例。圖 1 呈現的是完整的應用程序,其中顯示了從 Northwind 數據庫檢索到的產品列表。從 ListBox 中選擇了某個產品後,該產品將被綁定到頁面下半部分的控件上。當用戶通過 CheckBox 和 TextBox 控件編輯產品並單擊“Save”(保存)按鈕時,產品信息會隨即通過 WCF 發送到數據庫中。單擊“Cancel”(取消)按鈕可通過 WCF 從服務器獲得最新產品列表,同時更新 ListBox 及其綁定。

圖 1 示例 Silverlight 應用程序

Silverlight 2 示例應用程序由為數不多的幾個用戶控件和樣式構成。表現層利用異步調用通過 WCF 與服務器進行通信。它使用 WCF 服務引用並依照服務的操作約定和數據約定來實現 Silverlight 應用程序與服務的通信。數據約定(例如 Product 或 Category 實體類)公開了服務器應用程序中的實體結構。這使得 Silverlight 應用程序的控件可以輕松綁定到這些實體的實例及其屬性上。操作約定定義了 Silverlight 應用程序調用 WCF 服務的方法。圖 2 顯示的是此體系結構的高層次概觀。

圖 2 示例應用程序的體系結構模型

我將從 WCF 服務本身著手,先利用較低的層開始構建示例應用程序。您可以通過在 Visual Studio® 中創新建一個 WCF 項目來構建可與 Silverlight 應用程序進行通信的 WCF 服務。只要 Silverlight 應用程序具有 basicHttpBinding 類型的綁定,它就可以調用標准的 WCF 服務。您必須確保自己可將 WCF 服務的默認綁定從 wsHttpBinding 更改為 basicHttpBinding,否則必須新建一個 basicHttpBinding 類型的綁定。例如,示例 WCF 服務宿主應用程序的 web.config 文件包含用來定義服務配置的以下 XML。請注意,端點綁定被定義為 basicHttpBinding:

<service behaviorConfiguration=
  "MySilverlightWcfService.NWServiceGatewayBehavior"
  name="MySilverlightWcfService.NWServiceGateway">
  <endpoint address=""
    binding="basicHttpBinding"
    contract="MySilverlightWcfService.INWServiceGateway" />
  <endpoint address="mex" binding="mexHttpBinding"
    contract="IMetadataExchange" />
</service>

作為創建 WCF 服務的替代方法,您可以在 Visual Studio 中選擇文件項目模板來創建啟用 Silverlight 的 WCF 服務。圖 3 顯示的是 Visual Studio 中的新項目模板。此模板會自動將綁定設置為 basicHttpBinding 並添加一些屬性,以使服務與 ASP.NET 兼容。盡管此方法可為您設置正確的綁定配置,但不要忘記您仍可使用現有的 WCF 服務,但前提是這些綁定是針對 basicHttpBinding 設置的。

圖 3 啟用 Silverlight 的 WCF 模板

WCF 服務必須能夠請求產品列表來填充 ListBox,而且必須能夠保存用戶對產品所做的任何更改。這都是一些簡單的操作,無需專門的 Silverlight 技術。示例應用程式使用一個名為 NWServiceGateway 的 WCF 服務類,用於實現接口 INWServiceGateway。此處所示的 INWServiceGateway 被修飾為 ServiceContract,它可以使實現此接口的所有類都通過 WCF 加以公開:

[ServiceContract(Namespace = "")]
public interface INWServiceGateway
{
  [OperationContract]
  Product FindProduct(int productId);
  [OperationContract]
  List<Product> FindProductList();
  [OperationContract(Name="FindProductListByCategory")]
  List<Product> FindProductList(int categoryID);
  [OperationContract]
  List<Category> FindCategoryList();
  [OperationContract]
  void SaveProduct(Product product);
}

該接口列出了使用 OperationContract 屬性修飾的多種方法。OperationContracts 可通過 WCF 服務調用。請注意,FindProductList 方法具有兩個重載。一個接受參數,而另一個不接受。盡管這一點在 Microsoft® .NET Framework 方法中是完全可以接受的,但 WCF 卻無法公開具有相同名稱的兩個方法。要解決此問題,您可以重命名該方法或在服務定義中使用 OperationContract 的 Name 屬性指定一個不同的名稱。圖 4 顯示的是如何在 WCF 服務中向一個使用了新名稱的操作公開 FindProductList 方法及參數。

圖 4 在數據層中收集產品

public List<Product> FindProductList()
{
  var productList = new List<Product>();
  using (var cn = new SqlConnection(nwCn))
  {
    const string sql = @"SELECT p.*, c.CategoryName "
      + " FROM Products p INNER JOIN Categories c ON "
      + " p.CategoryID = c.CategoryID ORDER BY p.ProductName";
    cn.Open();
    using (var cmd = new SqlCommand(sql, cn))
    {
      SqlDataReader rdr = cmd.ExecuteReader(
        CommandBehavior.CloseConnection);
      if (rdr != null)
        while (rdr.Read())
        {
          var product = CreateProduct(rdr);
          productList.Add(product);
        }
      return productList;
    }
  }
}

WCF 服務需要做的只是實現此服務約定接口並調用一個 Manager 類,此類的任務是從數據庫獲取產品並將其映射到 List<Product>,以便它們可以從服務中傳送出去。圖 4 顯示的是用來從 Northwind 數據庫獲取產品列表、將各個產品映射到 Product 類並將各個產品實例添加到 List<Product> 中的代碼。

由 WCF 返回的實體必須用 DataContract 屬性進行修飾,以使其能夠被正確序列化並發送給 Silverlight 應用程序。圖 4 中涉及的 Product 類具有 DataContract 屬性,並且它的所有屬性都使用 DataMember 屬性加以修飾。這將告知 WCF 開始序列化並將實體及其 DataMember 屬性提供給 Silverlight 應用程序使用。當調用 WCF 服務的 FindProductList 方法時,Silverlight 客戶端應用程序將接收 List<Product>,並且將能夠引用使用 DataMember 屬性修飾的所有特性。

跨域通信

Silverlight 應用程序將在客戶端計算機環境中執行。這就會產生一些問題,即基於 ASP.NET Web 的應用程序當前並不會顯示出來,因為它們都是在服務器上執行而在客戶端上呈現 HTML 和編寫腳本代碼。由於 Silverlight 是在客戶端上執行的,因此它必須使用面向服務的技術(如 WCF)從該服務器請求信息。不過,必須要對 WCF 服務進行保護以防止某些不必要的客戶端應用程序利用它。示例 Silverlight 應用程序承載在您信任的 Web 服務器上,因此應允許它與示例應用程序的 WCF 服務進行交互。如果承載在另一 Web 服務器上的其他應用程序試圖與示例 WCF 服務進行通信,應將其拒絕。

對這種服務訪問的控制是通過跨域策略文件進行處理的。Adobe Flash 應用程序有一個標准文件,可用來處理這個名為 CrossDomain.xml 的文件(位於該服務的 Web 服務器的根目錄下)。Silverlight 應用程序的行為也非常相似,首先在 Web 服務器的根目錄(不是 Web 應用程序的根目錄)中查找名為 ClientAccessPolicy.xml 的文件。如果找到該文件,應用程序將讀取它以確定是允許還是拒絕請求。如果未找到,應用程序將繼續查找 CrossDomain.xml 文件。如果均未找到,該請求將被拒絕,且 Silverlight 客戶端應用程序也將無法調用該 WCF 服務。

每個文件的內容都必須允許調用方具有對這些服務的權限。由於示例應用程序僅存在於受保護的開發計算機中,因此其 ClientAccessPolicy.xml 將允許所有請求,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
 <cross-domain-access>
  <policy>
   <allow-from http-request-headers="*">
    <domain uri="*"/>
   </allow-from>
   <grant-to>
    <resource path="/" include-subpaths="true"/>
   </grant-to>
  </policy>
 </cross-domain-access>
</access-policy>

我創建的 ClientAccessPolicy.xml 文件允許從所有位置跨域訪問全部路徑。此文件的副本包括在示例應用程序中。在首次創建 WCF 項目後,默認選項將使用已被自動分配端口的 Visual Studio Development Server。但是,示例應用程序的 WCF 服務項目被設置為“使用 IIS Web Server”,此設置可以在 Web 選項卡的項目屬性頁面中進行更改。只要 ClientAccessPolicy.xml 文件被放置在 Web 站點的根目錄下,每個選項就都有效。

這些策略可加以限制,以僅允許某些 URI 能夠訪問特定文件夾路徑中的特定服務。要執行此操作,必須在此文件中指定承載 Silverlight 應用程序的 Web 服務器,這樣它才能與 WCF 服務交互。例如,受限程度較高的跨域策略可能如下所示:

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
 <cross-domain-access>
  <policy>
   <allow-from http-request-headers="*">
    <domain uri="http://johnpapa.net"/>
   </allow-from>
   <grant-to>
    <resource path="/MyAwesomeServices/" include-subpaths="true"/>
   </grant-to>
  </policy>
 </cross-domain-access>
</access-policy>

請注意,源自 johnpapa.net 中某項服務的任何請求都被允許訪問服務器上 /MyAwesomeServices 路徑下的服務。

調試具有跨域調用的問題可能有一些難度。您可以使用諸如 Web Development Helper(我的最愛)或 Fiddler 之類的工具來檢查 Silverlight 應用程序與基於服務器的服務之間的通信流量。這些工具將顯示各個單獨的 HTTP 請求和響應。您還應確保 ClientAccessPolicy.xml 文件被放置在 Web 根目錄下,而不是應用程序根目錄下。我不再占用篇幅來強調這一點。

此外,當在 Visual Studio 項目中承載服務時(例如,未直接位於 IIS 中),該項目會創建一個自動分配的端口,測試此服務的最簡單方法是將 ClientAccessPolicy.xml 文件放置在項目自身的根目錄下。由於該項目得到了一個自動分配的端口(如 localhost:32001/MyAwesomeService),它將在 Web 的根目錄下尋找 ClientAccessPolicy.xml 文件(在本例中為 localhost:32001)。

Silverlight 客戶端

編譯好這些服務並建立了跨域策略後,即可建立 Silverlight 客戶端以與 WCF 服務進行通信。示例應用程序中有一個名為 SilverlightWCF 的 Silverlight 客戶端項目,它需要一個對示例 WCF 服務的服務引用。在“Solution Explorer”(解決方案資源管理器)中右鍵單擊引用節點,然後選擇“Add Service Reference”(添加服務引用)。輸入該服務的 URL,單擊“GO”(搜索)按鈕,服務將會顯示出來。單擊“OK”(確定),服務客戶端配置以及生成的代理類將被添加到 Silverlight 項目中,以簡化調用服務和使用實體(如 DataContract 所定義)的過程。圖 5 顯示的是添加服務時出現的對話窗口。

圖 5 添加服務引用

請注意,默認情況下此示例將使用位於 localhost/MySilverlightWcfService/NWServiceGateway.svc 目錄下的服務。毋庸置疑,如果移動了該服務,則此端點地址也需要相應的更新。如果在 WCF 服務中進行了少量更改(如添加新方法或 DataContract),您可以在“Solution Explorer”(解決方案資源管理器)中選擇“ Update Service Reference”(更新服務引用)。

綁定產品列表

示例應用程序需要向用戶顯示產品列表。在這裡 ListBox 控件將與 DataTemplate 配合使用,這樣就可以在展示產品時帶有一些特殊效果,而不再是簡單地在行和列中列出值(ListBox 最初如圖 1 所示)。通過設置 ListBox 的 ItemSource 屬性,我們指明 ListBox 將從綁定數據源中獲取它的值,如以下標記所示:

<ListBox x:Name="lbProducts" Height="220" HorizontalAlignment="Left"
  VerticalAlignment="Bottom" Margin="10,10,10,10" Width="480"
  Style="{StaticResource ListBoxStyle}"
  ItemsSource="{Binding}" >

請注意,ItemSource 屬性只指明它將被綁定,而無法指明任何具體的對象或屬性。由於未指定任何源,ListBox 將引用 XAML 中任意繼承的 DataContext 對象源。DataContext 可從任何父 FrameworkElement 中繼承。在 WCF 服務返回產品列表後,示例應用程序將在代碼隱藏中設置 ListBox 的 DataContext,其名稱為 lbProducts:

lbProducts.DataContext = productList;

在執行此代碼後,ListBox 將被綁定到產品列表,而 DataTemplate 中的每個 ListBoxItem 都被綁定到列表中的各個產品上。圖 6 顯示的是用於創建 ListBox 並將 DataTemplate 中展示的項目綁定到源的 XAML。請注意,被綁定到源的各個控件將使用綁定標記擴展來指示它們將被綁定到 Product 的哪個屬性,並指出將使用 OneWay 綁定模式。例如,

Text="{Binding ProductName, Mode=OneWay}"

圖 6 ListBox XAML

<ListBox x:Name="lbProducts" Height="220" HorizontalAlignment="Left"
  VerticalAlignment="Bottom" Margin="10,10,10,10" Width="480"
  Style="{StaticResource ListBoxStyle}" ItemsSource="{Binding}" >
  <ListBox.ItemTemplate>
   <DataTemplate>
     <StackPanel Orientation="Horizontal">
      <StackPanel Style="{StaticResource TitlePanel}"
        Orientation="Vertical">
      <TextBlock Text="{Binding ProductName, Mode=OneWay}"
        Style="{StaticResource TitleTextBlock}" FontSize="14"/>
      <TextBlock Text="{Binding CategoryName, Mode=OneWay}"
        Style="{StaticResource SubTitleTextBlock}"/>
     </StackPanel>
      <Grid>
        <Grid.RowDefinitions>
         <RowDefinition></RowDefinition>
         <RowDefinition></RowDefinition>
         <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
         <ColumnDefinition></ColumnDefinition>
         <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <TextBlock Text="Product ID" Style="{StaticResource
         TextBlockStyle}" Grid.Row="0" Grid.Column="0"/>
        <TextBlock Text="{Binding Id, Mode=OneWay}"
         Style="{StaticResource TextBlockStyle}"
         Foreground="#FF001070" Grid.Row="0" Grid.Column="1"/>
        <TextBlock Text="Price" Style="{StaticResource
         TextBlockStyle}"
         Grid.Row="1" Grid.Column="0"/>
        <TextBlock Text="{Binding UnitPrice, Mode=OneWay,
         Converter={StaticResource
         priceConverter}}"
         Foreground="#FF001070" Style="{StaticResource
         TextBlockStyle}" Grid.Row="1" Grid.Column="1"/>
        <TextBlock Text="Units" Style="{StaticResource
         TextBlockStyle}" Grid.Row="2" Grid.Column="0"/>
        <TextBlock Text="{Binding UnitsInStock, Mode=OneWay}"
         Foreground="#FF001070"
         Style="{StaticResource TextBlockStyle}"
         Grid.Row="2" Grid.Column="1"/>
      </Grid>
     </StackPanel>
   </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

所有綁定 TextBox 控件的綁定模式都被設置為 OneWay。這表示源(即 Product 實例)在最初加載時以及當源中發生任何變更時都應將其值推至目標(ListBox 和其中綁定的任意項目)(有關“模式”的詳細信息,請參閱“綁定模式”部分)。

異步通信

在綁定得以完成之前,必須從 WCF 服務中獲取產品列表。Silverlight 中的所有 WCF 服務調用都是通過異步通信進行的。示例 WCF 服務發布了一個名為 FindProductList 的 OperationContract。由於與 Silverlight 的通信是異步的,因此這一約定是使用異步方法(此異步方法可啟動在操作完成時所引發的通信和事件)在生成的代理中實現的。

以下代碼將創建一個服務代理實例:

private void FindProductList()
{
  this.Cursor = Cursors.Wait;
  var proxy = new NWServiceGatewayClient();
  proxy.FindProductListCompleted += new
    EventHandler<FindProductListCompletedEventArgs>(
    FindProductListCompleted);
  proxy.FindProductListAsync();
}

代理創建完成後,將向 FindProductListCompleted 事件添加一個事件處理程序。這就是將要接收異步 WCF 服務調用結果的方法。最後執行 FindProductListAsync 方法。

當異步 WCF 服務調用完成後,將執行事件處理程序。以下代碼顯示了事件處理程序 FindProductListCompleted 接收產品列表並將其綁定到 ListBox 的 DataContext 的過程:

private void FindProductListCompleted(object sender,
  FindProductListCompletedEventArgs e)
{
  ObservableCollection<Product> productList = e.Result;
  lbProducts.DataContext = productList;
  if (lbProducts.Items.Count > 0)
    lbProducts.SelectedIndex = 0;
  this.Cursor = Cursors.Arrow;
}

產品詳細信息和綁定模式

在 ListBox 中選擇了某個項目後,事件處理程序中的代碼將從 ListBox 的 SelectedItem 中獲取所選的 Product,然後將其設置為 Grid 布局控件的 DataContext。Grid 布局控件被用作產品詳細信息部分的容器,其中包含一系列可供用戶對所選產品進行編輯的控件。由於 DataContext 是在控件樹中自上而下繼承的,因此無需在各個 TextBox 和 CheckBox 控件中設置 DataContext。這些控件都是從其父 Grid 控件(已在 lbProducts_SelectionChanged 事件處理程序中設置)繼承 DataContext 而來。

Grid 布局控件中有多個包含綁定聲明的 TextBlock、TextBox 和 CheckBox 控件。此部分的幾個 XAML 代碼段如下所示:

<TextBox Style="{StaticResource TextBoxStyle}"
  Text="{Binding UnitsInStock, Mode=TwoWay}"
  Grid.Row="1" Grid.Column="1" Margin="3,3,3,3" Height="30"
  x:Name="tbUnitsInStock" Width="100"
  VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<TextBlock Style="{StaticResource TextBlockStyle}" Text="{Binding
  CategoryName, Mode=OneWay}" Foreground="#FF001070" Grid.Row="1"
  Grid.Column="4" Margin="3,3,3,3" Height="22"
  HorizontalAlignment="Left" VerticalAlignment="Bottom"/>

請注意,第一個代碼段表示的是 TextBox,它顯示 Product 源對象中的 UnitsInStock 屬性。第二個代碼段顯示的是 Product 實例的 CategoryName 屬性的值。請注意,TextBox 中綁定的 Mode 屬性被設置為 TwoWay,而在 TextBlock 中被設置為 OneWay(此為默認設置)。

綁定的 Mode 屬性是一個重要的綁定設置,可用於確定在目標與源之間發生綁定的頻率及方向。圖 7 顯示的是 Silverlight XAML 及其更新時可以使用的三種綁定模式。

圖 7 Silverlight XAML 中的三種綁定模式

綁定模式 OneTime OneWay TwoWay 在首次設置了 DataContext 後目標會進行相應更新 Yes Yes Yes 在源發生更改時目標會進行相應更新 No Yes Yes 在目標發生更改時源會進行相應更新 No No Yes

當應用程序啟動或 DataContext 發生更改時,OneTime 綁定將源發送到目標。OneWay 綁定也可以將源發送到目標。但是,如果源實現 INotifyPropertyChanged 接口,則當源發生更新時目標將接收到更新。TwoWay 綁定會將源數據發送到目標,但如果目標屬性的值發生更改,則會將這些更改返回給源。如果源對象實現 INotifyPropertyChanged 並且如果源的屬性 setter 引發了 PropertyChanged 事件,則 OneWay 和 TwoWay 綁定都只告知目標有關更改的消息。

在上一示例中,OneWay 綁定被用於 CategoryName,因為它顯示在 TextBlock 中而且無法進行編輯。TwoWay 綁定被用於 UnitsInStock,因為它顯示在可編輯的 TextBlock 中。當用戶在 TextBox 中編輯 UnitsInStock 的值且 TextBox 失去焦點時,更改結果將被發送回源對象。

OneTime 綁定最適合表示那些在顯示時從不會發生更改的只讀信息。OneWay 綁定適合表示那些在顯示過程中可能會在某個時刻發生更改的只讀信息。進一步說,如果在 CategoryName TextBlock 中使用了 OneTime 綁定而不是 OneWay 綁定,則單擊“取消”按鈕並且產品列表被刷新後,使用 OneTime 綁定模式的 TextBlock 將不會更新。最後,當用戶必須能夠更改某個控件中的數據並能夠使更改在數據源中反映出來時,最好選擇使用 TwoWay 綁定。

更改事件

當源發生更改時,使 OneWay 和 TwoWay 綁定通知目標的關鍵一點是實現 INotifyPropertyChanged 接口。Product 類可實現此接口,該類由單個事件 PropertyChanged 組成。PropertyChanged 事件接受發送者和發生更改的屬性的名稱作為參數。Silverlight 數據綁定偵聽這些來自數據源的事件。如果該類既不實現此接口也不在屬性 setter 中引發 PropertyChanged 事件,則目標將永遠不會收到更新。PropertyChangedEventHandler 在 Product 類中通過下列幾行代碼實現:

public override event PropertyChangedEventHandler PropertyChanged;

在這種情況下,該事件將被覆蓋而不是簡單地定義,因為 Product 類將從自定義的 EntityBase 類(此類可實現 INotifyPropertyChanged 接口)進行繼承。事實上,這裡介紹的 EntityBase 類可實現 PropertyChangedEventHandler,因此可以在 Product 或 Category 等派生類(如 )中將其覆蓋:

[DataContract]
public abstract class EntityBase : INotifyPropertyChanged  
{
  protected void PropertyChangedHandler(EntityBase sender,
    string propertyName)
  {
    if (PropertyChanged != null)
      PropertyChanged(sender, new PropertyChangedEventArgs(
        propertyName));
  }
  public virtual event PropertyChangedEventHandler PropertyChanged;
}

為方便起見,也可以使用 EntityBase 類為派生類定義 PropertyChangedHandler 方法,這反過來又可以引發 PropertyChanged 事件。這是一個簡單的重構過程,它可將引發事件的邏輯放置到單一位置上並可減少代碼量。例如,具有 UnitPrice 屬性的 product 類可設置產品價格值並調用基礎類的 PropertyChangedHandler 方法:

[DataMember]
public decimal UnitPrice
{
  get { return _unitPrice; }
  set
  {
    _unitPrice = value;
    base.PropertyChangedHandler(this, "UnitPrice");
  }
}

此方法反過來又會引發 PropertyChanged 事件。然後此事件將被發送到任意 OneWay 或 TwoWay 綁定,從而使這些綁定將目標控件更新為新值。Product 類中每個屬性的 setter 都使用此模式。

屬性更改通知可通過示例應用程序進行演示,方法是從 ListBox 中選擇一個產品,然後在 TextBox 中編輯單價。由於 tbUnitPrice TextBox 使用 TwoWay 綁定,這會使新價格被發送到源。一旦源被更新,即會引發 PropertyChanged 事件。這會使偵聽此事件的所有綁定都更新目標值。由於 ListBox 實現 OneWay 綁定,因此價格值會自動將其自身更新為新的價格值。

如您所見,利用示例應用程序中所示的聲明式綁定語法可輕松實現 Silverlight 2 數據綁定功能。這些綁定將偵聽 PropertyChanged 事件,以便能夠更新其目標。在本專欄中,我向您演示了通過 Silverlight 實現綁定的容易程度,並介紹了以何種方式與 WCF 服務通信才能與業務對象和數據庫進行交互,還介紹了如何定義 ClientAccessPolicy.xml 文件以允許和限制遠程通信。

請將您想向 John 詢問的問題和提出的意見發送至 [email protected]

John Papa (johnpapa.net) 是 ASPSOFT (aspsoft.com) 的一位資深顧問,同時也是一位狂熱的棒球謎,在夏季的大多數夜晚,他都會與家人一起為美國的洋基隊吶喊助威。John 是 C# 領域的 MVP 和 INETA 發言人,他曾撰寫過多本著作,現在正忙於撰寫新書《Data Access with Silverlight 2》,該書將由 O'Reilly 於 2008 年 12 月出版。他經常在一些會議(如 DevConnections 和 VSLive)上發表演講。

代碼下載位置:SLDataServices2008_09a.exe (234 KB)

http://download.microsoft.com/download/f/2/7/f279e71e-efb0-4155-873d-5554a0608523/SLDataServices2008_09a.exe

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved