1. 程式人生 > >WPF教程(二)DataContext繫結資料

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介面,後續章節會介紹。