Silverlight 2 (Beta 2) 引入了強大的 XAML 資料繫結、控制項範本與 WCF 非同步通訊能力,使得構建企業級豐富互聯網應用 (RIA) 成為可能。本文基於 MSDN 專欄實例,完整演示從 WCF 服務建置、跨域策略配置、Silverlight 客戶端開發、ListBox 資料模板繫結、非同步服務呼叫、ThreeWay/TwoWay/OneWay 繫結模式選擇,到 INotifyPropertyChanged 變更通知機制的端到端實作。
basicHttpBinding) + ClientAccessPolicy.xml 跨域授權Product, Category 標註 [DataContract]/[DataMember] 透過 WCF 序列化傳輸Silverlight 2 僅支援 basicHttpBinding (SOAP 1.1 / HTTP)。wsHttpBinding 會導致通訊失敗。
<endpoint address="" binding="basicHttpBinding" contract="MyService.INWServiceGateway" />
或使用 VS 模板 "Silverlight-enabled WCF Service" 自動配置。
Silverlight 執行於客戶端瀏覽器沙箱,呼叫不同網域/埠/協定的服務需授權。瀏覽器依序尋找:
ClientAccessPolicy.xml (Silverlight 專用,優先)crossdomain.xml (Flash 相容)檔案必須置於 **Web 站點根目錄** (非應用程式虛擬目錄)。
<?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>
除錯提示:使用 Fiddler / Web Development Helper 檢查 HTTP 流量;確認策略檔在網站根目錄 (如 https://localhost:port/ClientAccessPolicy.xml 可下載)。
專案右鍵 → "Add Service Reference" → 輸入服務 URL → 命名空間。產生代理類 NWServiceGatewayClient 與實體類 (Product, Category)。
<ListBox x:Name="lbProducts" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding ProductName, Mode=OneWay}" FontSize="14"/>
<TextBlock Text="{Binding CategoryName, Mode=OneWay}"/>
</StackPanel>
<Grid>
<TextBlock Text="Price:"/>
<TextBlock Text="{Binding UnitPrice, Mode=OneWay, Converter={StaticResource priceConverter}}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
程式碼後置設定 lbProducts.DataContext = productList; 即完成繫結。
private void FindProductList()
{
this.Cursor = Cursors.Wait;
var proxy = new NWServiceGatewayClient();
proxy.FindProductListCompleted += FindProductListCompleted;
proxy.FindProductListAsync(); // 非同步啟動
}
private void FindProductListCompleted(object sender, FindProductListCompletedEventArgs e)
{
var productList = e.Result; // ObservableCollection
lbProducts.DataContext = productList;
if (lbProducts.Items.Count > 0) lbProducts.SelectedIndex = 0;
this.Cursor = Cursors.Arrow;
}
| 模式 | 初始化時更新目標 | 來源變更更新目標 | 目標變更更新來源 | 適用場景 |
|---|---|---|---|---|
| OneTime | ✓ | ✗ | ✗ | 靜態唯讀資料 (版權聲明、固定標籤) |
| OneWay | ✓ | ✓ (需 INotifyPropertyChanged) | ✗ | 動態唯讀資料 (清單顯示、詳情檢視) |
| TwoWay | ✓ | ✓ (需 INotifyPropertyChanged) | ✓ (失去焦點時) | 可編輯表單欄位 (TextBox, CheckBox, ComboBox) |
ProductName (ListBox TextBlock) → OneWayCategoryName (Detail TextBlock) → OneWayUnitsInStock (Editable TextBox) → TwoWayUnitPrice (Editable TextBox) → TwoWay + Converter 格式化來源物件必須實作 INotifyPropertyChanged,在屬性 Setter 中引發 PropertyChanged 事件,繫結引擎才能感知變更並更新目標。
[DataContract]
public abstract class EntityBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
[DataContract]
public class Product : EntityBase
{
private decimal _unitPrice;
[DataMember]
public decimal UnitPrice
{
get { return _unitPrice; }
set
{
if (_unitPrice != value)
{
_unitPrice = value;
OnPropertyChanged("UnitPrice"); // 觸發通知
}
}
}
// 其他屬性同理...
}
UnitPrice (TwoWay)Product.UnitPricePropertyChanged("UnitPrice")UnitPrice (OneWay) 的 TextBlock 自動更新顯示新價格private void btnCancel_Click(object sender, RoutedEventArgs e)
{
// 重新從服務取得最新資料,覆寫 DataContext
proxy.FindProductListAsync(); // 完成事件中重設 DataContext
}
若繫結模式為 OneTime,重設 DataContext 也不會更新 UI;OneWay/TwoWay 會自動重繫結更新。
Silverlight 2 + WCF 為 RIA 開發奠定了堅實基礎:basicHttpBinding 互通性、ClientAccessPolicy.xml 安全跨域、非同步 APM 模式、聲明式 XAML 繫結、三種繫結模式精準控制、INotifyPropertyChanged 響應式 UI。掌握這些核心機制,您將能構建出既美觀又健壯的企業級 Silverlight 應用程式。