前面章節一直都在討論如何添加連接兩個各元素的綁定。但在數據驅動的應用程序中,更常見的狀況是建立從不可見對象中提取數據的綁定表達式。惟一的要求是但願顯示的信息必須存儲在公有屬性中。WPF數據綁定數據結構不能獲取私有信息或公有字段。正則表達式
當綁定到非元素對象時,須要放棄Binding.ElementName屬性,並使用如下屬性中的一個:數據結構
1、Source屬性工具
Source屬性很是簡單。惟一的問題是爲了進行綁定,須要具備數據對象。在稍後將看到可以使用集中方法獲取數據對象。可從資源中提取數據對象,可經過編寫代碼生成數據對象,也可在數據提供的幫助下獲取數據對象。字體
最簡單的選擇是將Source屬性指向一些已經準備好了的靜態對象。例如,可在代碼中建立一個靜態對象並使用該對象。或者,可以使用來自.NET類庫的組件。以下所示:spa
<TextBlock Margin="5" Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=Source}"></TextBlock>
這個綁定表達式獲取由靜態屬性SystemFonts.IconFontFamily提供的FontFamily對象(注意,爲了設置Binding.Source屬性,須要藉助靜態標記擴展)。而後將Binding.Path屬性設置爲FontFamily.Source屬性,給屬性給出了字體家族的名稱。結果是一行文本。在Windows Vista或Windows 7中,顯示的字體名稱segoe UI。code
另外一種選擇是綁定到先前做爲資源建立的對象。例如,下面的標記建立指向Calibri字體的FontFamily對象:對象
<Window.Resources> <FontFamily x:Key="CustomFont">Calibri</FontFamily> </Window.Resources>
而且下面的TextBlock元素會被綁定到該資源:blog
<TextBlock Margin="5" Text="{Binding Source={StaticResource CustomFont}, Path=Source}"></TextBlock>
如今將會看到文本Calibri。ci
2、RelativeSource屬性資源
經過RelativeSource屬性可根據相對於目標對象的關係指向源對象。例如,可以使用RelativeSource屬性將元素綁定到自身或其父元素(不知道在元素樹中從當前元素到綁定的父元素到綁定的父元素之間有多少代)。
爲設置Binding.RelativeSource屬性,須要使用RelativeSource對象,這會使語法變得更加複雜,由於出了須要建立Binding對象外,還須要在其中建立嵌套的RelativeSource對象。一種選擇是使用屬性設置語法而不是使用Binding標識擴展。例如,下面的代碼爲TextBlock.Text屬性建立了一個Binding對象,這個Binding對象時候用查找父窗口並顯示窗口標題的RelativeSource對象:
<TextBlock> <TextBlock.Text> <Binding Path="Title"> <Binding.RelativeSource> <RelativeSource Mode="Findncestor" AncestorType="{x:Type Window}" /> </Binding.RelativeSource> </Binding> </TextBlock.Text> </TextBlock>
RelativeSource對象使用FindAncestor模式,該模式告知查找元素樹直到發現AncestorType屬性定義的元素類型。
編寫綁定更經常使用的方法是使用Binding和RelativeSource標記擴展,將其合併到一個字符串中,以下所示:
<TextBlock Text="{Binding Path=Title,RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}} }"> </TextBlock>
當建立RelativeSource對象時,FindAncestor模式有4中,下表列出了全部4中模式。
表 RelativeSourceMode枚舉值
RelativeSource屬性看似多餘,而且會標記變得複雜。畢竟,爲何不使用Source或Element屬性直接綁定到但願使用的源呢?然而,並不老是可使用Source或ElementName屬性,這一般是由於源對象和目標對象在不一樣的標記塊中。當建立控件模板和數據模板時會出現這種狀況。例如,若是正在構建改變列表項顯示方式的數據模塊,可能須要訪問頂級ListBox對象以讀取屬性。
3、DataContext屬性
在某些狀況下,會將大量元素綁定到同一個對象。例如,分析下面的一組TextBlock元素,每一個TextBlock元素都使用相似的綁定表達式提取與默認圖標字體相關的不一樣細節,包括行間距,以及第一個字體的樣式和粗細(這兩個都是簡單的正則表達式)。可爲每一個TextBlock元素使用Source屬性,但這會使標記變得很是長:
<TextBlock Margin="5" Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=LineSpacing}"></TextBlock> <TextBlock Margin="5" Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=FamilyTypefaces[0].Style}"></TextBlock> <TextBlock Margin="5" Text="{Binding Source={x:Static SystemFonts.IconFontFamily}, Path=FamilyTypefaces[0].Weight}"></TextBlock>
對於這種狀況,使用FrameworkElement.DataContext屬性一次性定義綁定源會更清晰,也更靈活。在這個示例中,爲包含全部TextBlock元素的StackPanel面板設置DataContext屬性是合理的(甚至還可在更高層次上設置DataContext屬性——例如整個窗口——可是爲了使意圖更清晰,在儘量小的範圍內進行定義效果更好)。
可以使用和設置Binding.Source屬性相同的方法設置元素的DataContext屬性。換句話說,可提供內聯對象,從靜態屬性中提取,或從資源中提取,以下所示:
<StackPanel Margin="10" DataContext="{x:Static SystemFonts.IconFontFamily}">
如今可經過省略源信息來精簡綁定表達式:
<TextBlock Margin="5" Text="{Binding Path=Source}"></TextBlock>
當在綁定表達式中省略源信息時,WPF會檢查元素的DataContext屬性。若是屬性值爲null,WPF會繼續向上在元素樹中查找第一個不爲null的數據上下文(最初,全部元素的DataContext屬性都是null)。若是找到了一個數據上下文,就爲綁定使用找到的數據上下文。若是沒有找到,綁定表達式不會爲目標屬性應用任何值。