WPF教程(二)DataContext繫結資料
(一)基礎知識
DataContext屬性是繫結的預設源,除非你具體指定了另外一個源,比如我們使用了ElementName屬性。它由FrameworkElement類定義,大部分UI控制元件包括WPF視窗都繼承於此類。簡單地說,它允許你指定一個繫結的基。
DateContext並沒有預設源(剛開始的時候是NULL),但是它貫穿整個空間層次結構,你可以為視窗設定一個DataContext,然後在任意的子控制元件裡面使用它。讓我們用程式碼來舉例說明:
Window x:Class="WpfTutorialSamples.DataBinding.DataContextSample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="DataContextSample" Height="130" Width="280"> <StackPanel Margin="15"> <WrapPanel> <TextBlock Text="Window title: " /> <TextBox Text="{Binding Title, UpdateSourceTrigger=PropertyChanged}" Width="150" /> </WrapPanel> <WrapPanel Margin="0,10,0,0"> <TextBlock Text="Window dimensions: " /> <TextBox Text="{Binding Width}" Width="50" /> <TextBlock Text=" x " /> <TextBox Text="{Binding Height}" Width="50" /> </WrapPanel> </StackPanel> </Window>
using System; using System.Windows; namespace WpfTutorialSamples.DataBinding { public partial class DataContextSample : Window { public DataContextSample() { InitializeComponent(); this.DataContext = this; } } }
後臺程式碼只添加了一行有意思的程式碼:在標準InitalizeComponent()呼叫之後,我們將“this”賦值給DataContext,這將告訴視窗我們系統視窗本身作為資料上下文。
在XAML中,我們綁定了視窗的一些屬性值,如Title,Width和Height。由於視窗有一個DataContext,它可以傳遞給子控制元件,我們不再需要給每一個繫結定義一個源。如果這些屬性是全域性變數,直接使用它們的值就行。
執行上面的程式碼,然後改變視窗大小,你會發現高和寬的值會立馬改變。如果編寫一個不同的標題在第一個文字框裡,你會發現標題並沒有立即被改變。相反地,你必須將游標移動到其他控制元件上改變才會生效。為什麼會這樣?這是下一章的主題。(注:我在VS2012裡面試這個例子,標題是立即實時改變的)
(二)DataContext繫結資料
在XAML中設定DataContext,注意要設定:1)引用namespace;2)設定Resources;3)設定DataContext。如下程式碼所示:
<Window x:Class="DataContext.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:DataContext"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:People x:Key="pep" Name="Peter"/>
</Window.Resources>
<Grid>
<StackPanel Margin="15">
<WrapPanel Margin="0,20,0,0" Name="WrapPanel" DataContext="{StaticResource pep}">
<TextBox Text="{Binding Path=Name}" Width="50" Margin="5,0"/>
</WrapPanel>
</StackPanel>
</Grid>
</Window>
或者
<Window x:Class="DataContext.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local ="clr-namespace:DataContext"
Title="MainWindow" Height="350" Width="525">
<Grid>
<StackPanel Margin="15">
<WrapPanel Margin="0,20,0,0" Name="WrapPanel">
<WrapPanel.DataContext>
<local:People Name="Hyman"/>
</WrapPanel.DataContext>
<TextBox Text="{Binding Path=Name}" Width="50" Margin="5,0"/>
</WrapPanel>
</StackPanel>
</Grid>
</Window>
或者後臺繫結
public void Init()
{
People pep= new People ();
pep.Name = Peter;
WrapPanel.DataContext = pep;//僅WrapPanel內的所有元素可以繫結此資料
}
總結
使用DataContext屬性就好像設定了所有繫結的基礎,能夠貫穿整個控制元件層次。這樣就節省了手動為每一個繫結定義源,一旦你真正開始使用資料繫結,肯定會感激如此節省的時間。
但是,這並不意味著你必須在一個窗口裡面為所有控制元件使用同樣的DataContext。由於每一個控制元件都有其自己的DataContext屬性,你可以很容易的打破繼承鏈,用新值來重寫DataContext。這就允許你在窗口裡使用一個全域性DataContext,然後在像panel這樣的地方使用本地具體的DataContext,以一種獨立的格式或者像上面的列出的那樣。
另外,以上繫結之後當修改資料內容時介面顯示並不會更改,要實現更改資訊傳遞給使用者介面,資料類必須實現INotifyPropertyChanged介面,後續章節會介紹。