首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 資料繫結核心技術全景解析:從基礎語法到驗證、轉換與資料模板

     編輯:關於.NET

Binding:WPF UI 與資料模型的「通用介面卡」

System.Windows.Data.Binding 類別是 WPF 資料繫結的核心,它在「目標」(必須為 DependencyProperty)與「來源」(任意 CLR 物件、XML 節點、另一個 UI 元素)之間建立雙向或單向同步通道。一旦建立,繫結引擎自動處理變更通知、型別轉換、驗證、格式化,開發者無需手寫同步程式碼。

四大繫結場景完整範例

1. UI 元素間繫結 — 最純粹的依賴屬性連結

<TextBox x:Name="src" Text="來源文字"/>
<TextBlock Text="{Binding ElementName=src, Path=Text}"/>
<TextBlock Text="{Binding ElementName=src, Path=ActualWidth, StringFormat='寬度: {0}px'}"/>

C# 等價程式碼:

var b = new Binding { Source = src, Path = new PropertyPath("Text") };
target.SetBinding(TextBlock.TextProperty, b);
// 移除繫結:BindingOperations.ClearBinding(target, TextBlock.TextProperty);
// 或直接指派新值:target.Text = "固定值";

關鍵屬性:ElementName/Source/RelativeSource 三選一指定來源;Path 指定屬性路徑;Mode(OneWay/TwoWay/OneTime/OneWayToSource/Default);UpdateSourceTrigger(PropertyChanged/LostFocus/Explicit/Default)。

2. 集合繫結 — ItemsSource + INotifyCollectionChanged

任何 IEnumerable 皆可作為 ItemsSource,但需 集合變更通知 才能讓 UI 自動增刪項目。標準做法:集合類別繼承 ObservableCollection<T>(已實作 INotifyCollectionChanged + INotifyPropertyChanged)。

public class Photos : ObservableCollection<Photo> { }
<ListBox x:Name="lb" ItemsSource="{Binding Source={StaticResource photos}}" DisplayMemberPath="Name"/>

DisplayMemberPath 指定顯示屬性;複雜呈現改用 ItemTemplate(見資料模板章節)。

3. DataContext 共享繫結 — 容器層級資源流向

<StackPanel DataContext="{StaticResource myEmployee}">
  <TextBox Text="{Binding Path=FirstName}"/>
  <TextBox Text="{Binding Path=LastName}"/>
  <TextBox Text="{Binding Path=Title}"/>
</StackPanel>

子元素未指定 Source 時,向上邏輯樹尋找最近非空 DataContext。RelativeSource={RelativeSource AncestorType=Window} 可跨層級存取。

4. 資料模板 — 結構化視覺樹的可復用定義

適用於 ContentControl.ContentTemplate、ItemsControl.ItemTemplate、HeaderedContentControl.HeaderTemplate。模板內共享父繫結上下文:

<ListBox ItemsSource="{Binding}">
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Border BorderBrush="Gray" BorderThickness="1" Margin="2" Padding="4">
        <StackPanel Orientation="Horizontal">
          <Image Source="{Binding ThumbnailPath}" Width="48" Height="48"/>
          <StackPanel Margin="8,0">
            <TextBlock Text="{Binding Name}" FontWeight="Bold"/>
            <TextBlock Text="{Binding Date, StringFormat='yyyy-MM-dd'}" Foreground="Gray"/>
          </StackPanel>
        </StackPanel>
        <ToolTipService.ToolTip>
          <TextBlock Text="{Binding Description}"/>
        </ToolTipService.ToolTip>
      </Border>
    </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

模板可提升為資源字典 (ResourceDictionary) 跨視窗/專案共用。

值轉換器:繫結管線的「轉接頭」

實作 IValueConverter 介面,Convert(目標←源)、ConvertBack(目標→源)。註冊為資源後掛載於 Binding.Converter。

public class CountToTextConverter : IValueConverter {
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        int n = (int)value; return $"{n} {(n == 1 ? "項目" : "項目")}";
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => throw new NotSupportedException();
}
<Window.Resources>
  <local:CountToTextConverter x:Key="countConv"/>
</Window.Resources>
<TextBlock Text="{Binding Count, Converter={StaticResource countConv}}"/>

常見應用:BoolToVisibilityConverter、NullToVisibilityConverter、EnumToDescriptionConverter、ByteArrayToImageConverter 等。

驗證規則:繫結層級的資料完整性守門員

Binding.ValidationRules 集合接受繼承 ValidationRule 的類別。驗證發生於 Converter 之前,失敗即阻斷源更新並設定 Validation.HasError=True。

public class JpgFileRule : ValidationRule {
    public override ValidationResult Validate(object value, CultureInfo culture) {
        var path = (value ?? "").ToString();
        if (!File.Exists(path)) return new ValidationResult(false, "檔案不存在");
        if (!path.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase)) return new ValidationResult(false, "僅限 JPG 檔案");
        return ValidationResult.ValidResult;
    }
}

XAML 掛載並搭配即時觸發與錯誤模板(見前文章節)。

資料提供者:宣告式資料源

  • ObjectDataProvider:在 XAML 實例化任意類別並呼叫方法/屬性作為繫結源,支援 MethodParameters、ObjectInstance、ObjectType。
  • XmlDataProvider:載入 XML 文件(Source URI 或 Document 內嵌),搭配 XPath 查詢節點集合。
<ObjectDataProvider x:Key="employees" ObjectType="{x:Type local:EmployeeService}" MethodName="GetAll"/>
<ListBox ItemsSource="{Binding Source={StaticResource employees}}"/>

除錯技巧與效能提示

  • 繫結錯誤輸出視窗:VS 輸出視窗預設顯示繫結錯誤;嚴重者可在 PresentationTraceSources 提升等級:<Binding diag:PresentationTraceSources.TraceLevel=High>。
  • 避免巢狀深層 Path:Path=Order.Customer.Address.City 任一節點為 null 即中斷;ViewModel 暴露扁平屬性更穩健。
  • 大量項目虛擬化:VirtualizingStackPanel.IsVirtualizing="True" + ItemsPanel 設定 VirtualizingStackPanel。
  • 凍結 Freezable 資源:Brush、Transform 等標記 x:Shared="False" 或程式碼 Freeze() 跨執行緒共用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved