2011-08-31 75 views
26

由於問題Linking DataContext with another property in WPF的延續。什麼是DataContext?

在研究的最後我很驚訝地發現,當一個人寫這樣的事情:

<Label Content="{Binding Path=Name}" /> 

DataContext針對的Content屬性綁定是Label控制自己的!它仍然有效的事實是由於來自最近父級的DataContext值的默認繼承。

但是,如果你有這個標籤,包裹在一個自定義的控制,並且不希望將數據綁定到該控件的DataContext財產,你會更容易喜歡有:

<Controls:SearchSettings Settings="{Binding Path=Settings}" /> 

而且這個給你。現在,你需要設置SettingsDataContextSearchSettings控制,爲Label內綁定反對,但你不能,因爲這將引發再結合Settings財產。

我看不到在使用不同來源的混合綁定屬性點:DataContext,由ElementName等 那麼,爲什麼我會永遠使用DataContext

回答

78

,並不是myLabel.Name

WPF中的XAML只是一個漂亮的用戶界面,用於顯示實際數據並與之互動,否則稱爲DataContext。其他綁定源(RelativeSource,ElementName等)的用途是指向當前控件的不存在的另一個屬性DataContext


因此假設您有一個窗口。沒有設置DataContext,窗口仍然顯示,但沒有數據。

現在假設設置myWindow.DataContext = new ClassA();。現在窗口顯示的數據是ClassA。如果ClassA有一個名爲Name的屬性,我可以編寫一個標籤並將其綁定到Name(如您的示例),並且ClassA.Name中存儲的任何值都將顯示。

現在,假設ClassA有一個屬性ClassB和這兩個類都有一個屬性,稱爲Name。這裏是XAML的塊,說明在DataContext的目的,並控制將如何引用屬性不是在它自己的DataContext

<Window x:Name="myWindow"> <!-- DataContext is set to ClassA --> 
    <StackPanel> <!-- DataContext is set to ClassA --> 

     <!-- DataContext is set to ClassA, so will display ClassA.Name --> 
     <Label Content="{Binding Name}" /> 

     <!-- DataContext is still ClassA, however we are setting it to ClassA.ClassB --> 
     <StackPanel DataContext="{Binding ClassB}"> 

      <!-- DataContext is set to ClassB, so will display ClassB.Name --> 
      <Label Content="{Binding Name}" /> 

      <!-- DataContext is still ClassB, but we are binding to the Window's DataContext.Name which is ClassA.Name --> 
      <Label Content="{Binding ElementName=myWindow, Path=DataContext.Name}" /> 
     </StackPanel> 
    </StackPanel> 
</Window> 

正如你可以看到一個例子,在DataContext是基於什麼數據在UI對象後面。

更新:我看到這個問題,所以經常從我擴大這個答案進入我的博客後的新WPF用戶:What is this 「DataContext」 you speak of?

+0

嗨!感謝您的詳細解答。但。在你的例子中,我不喜歡的是你綁定了DataContext屬性本身。很可能我會將您的示例中的StackPanel提取到單獨的控件中。如果它的DataContext只是它的父類的DataContext的一個獨立部分,那麼它是有意義的,不是嗎?然後我不會綁定我的用戶控件的DataContext屬性,而是會擁有一個具有自描述名稱的特殊屬性。 (我的意思是什麼是特定控件的DataContext?我應該傳遞什麼?)這就是事情變得複雜了。 [待續] –

+0

因爲我不會綁定DataContext屬性,所以它將從父控件中獲取。這意味着我不再能夠將自定義控件中的控件綁定到DataContext上,僅僅因爲我不知道里面有什麼(控件無法控制它的子類,以及它將接收的DataContext)。解決方案可以是從內部設置DataContext來控制(使用該特殊屬性的值)。 –

+0

但是這會破壞控件本身的綁定,因爲正如你所指出的那樣,寫了'Content = {Binding Name}'綁定到'Label.DataContext.Name'而不是'Label.Parent。 DataContext.Name',就像我期望的那樣。 –

1

在這種特殊情況下,你可以這樣做:

<Controls:SearchSettings DataContext="{Binding Path=Settings}" Settings="{Binding}" /> 

假設你想,因爲它是數據上下文,可能是內容SearchSettings的的使用設置了一切。基本上,DataContext影響元素本身的任何後代,不明確覆蓋它。

0

在大多數情況下,您需要想要綁定到DataContext,在ItemsControls上的某些模板中,它是綁定到當前模板化項目的唯一方法。進一步綁定到DataContext很好,因爲它們是簡潔的,所以可以書寫和閱讀。

在你的榜樣,你仍然可以設置DataContext的,你只需要修改的設置分別綁定:當你寫

<Label name="myLabel" Content="{Binding Path=Name}" /> 

要綁定到myLabel.DataContext.Name

<Controls:SearchSettings DataContext="{Binding Settings}" Settings="{Binding}"/> 
+0

我以爲這種做法,但它沒有任何意義。爲什麼我應該綁定兩個屬性,如果我只需要一個? –

+0

@EugeneStrizhok:你不僅需要一個,這允許你綁定到子控件中的設置而無需設置源,因爲你現在可以使用DataContext。 –

1

CodeProject由紀Gaddam:

DataContext是一個數據綁定中最基本的概念。 Binding對象需要從某處獲取數據,並且有幾種方法可以指定數據源,例如直接在Binding中使用Source屬性,在樹中遍歷時從最近的元素繼承DataContext,將ElementName和Binding對象中的RelativeSource屬性。

在CodeProject詳細例如:http://www.codeproject.com/Articles/321899/DataContext-in-WPF

相關問題