WPF 繫結在來源資料物件與 UI 控制項間建立連結,支援單向或雙向變更通知,實現業務邏輯與介面的分離。標準模式:目標物件(通常為 XAML 元素)的目標屬性(必須為相依屬性),透過 Binding 物件繫結至資料來源(CLR 物件、ADO.NET DataTable、XML 等)。
<Window x:Class="Learn.WPF.Window1"
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="276" Width="360">
<Grid>
<StackPanel>
<TextBox x:Name="textbox1" />
<Button x:Name="btnGet" Content="Get Name" Click="buttonClick" />
<Button x:Name="btnSet" Content="Set Name" Click="buttonClick" />
</StackPanel>
</Grid>
</Window>
class MyData : DependencyObject
{
public static readonly DependencyProperty NameProperty =
DependencyProperty.Register("Name", typeof(string), typeof(MyData),
new UIPropertyMetadata("Hello, World!"));
public string Name
{
get { return (string)GetValue(NameProperty); }
set { SetValue(NameProperty, value); }
}
}
public partial class Window1 : Window
{
MyData data;
public Window1()
{
InitializeComponent();
data = new MyData();
var binding = new Binding("Name") { Source = data };
this.textbox1.SetBinding(TextBox.TextProperty, binding);
}
private void buttonClick(object sender, RoutedEventArgs e)
{
if (sender == btnSet)
data.Name = DateTime.Now.ToString();
else
MessageBox.Show(data.Name);
}
}
執行結果:
這展示雙向繫結預設行為,開發者只需關注業務邏輯或 UI 呈現,大幅降低耦合。
| 模式 | 說明 |
|---|---|
OneWay | 來源→目標單向更新,目標修改不回傳來源 |
TwoWay | 雙向同步(預設,視目標屬性而定) |
OneWayToSource | 目標→來源單向更新 |
OneTime | 僅初始化時從來源讀取一次 |
var binding = new Binding("Name") { Source = data, Mode = BindingMode.OneWay };
this.textbox1.SetBinding(TextBox.TextProperty, binding);
FrameworkElement.SetBinding 僅適用於繼承自 FrameworkElement 的元素,而 System.Windows.Data.BindingOperations 直接接受 DependencyObject,適用範圍更廣。
// 兩種寫法等價
this.textbox1.SetBinding(TextBox.TextProperty, binding);
BindingOperations.SetBinding(this.textbox1, TextBox.TextProperty, binding);
BindingOperations.ClearBinding(this.textbox1, TextBox.TextProperty);
XAML 中使用 {Binding ...} 標記延伸(無 Extension 後綴),支援多種繫結來源:
<TextBox x:Name="textbox1" />
<Label Content="{Binding ElementName=textbox1, Path=Text}" />
<Window.Resources>
<ContentControl x:Key="text">Hello, World!</ContentControl>
</Window.Resources>
<Label Content="{Binding Source={StaticResource text}}" />
注意: Binding.Source 非相依屬性,無法繫結至 DynamicResource。
<Label Content="{Binding RelativeSource={RelativeSource Self}, Path=Name}" />
<Grid x:Name="Grid1">
<Label Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=Name}" />
</Grid>
WPF 允許任意 .NET 物件作為繫結來源,但一般物件屬性變更無法自動通知 UI。需實作 INotifyPropertyChanged 介面:
public class Data : INotifyPropertyChanged
{
private string name;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get { return name; }
set
{
if (value != name)
{
name = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
}
}
實作後,來源物件屬性變更即可自動同步至 UI,達成真正的雙向繫結。