2010-03-03 19 views
2

我敢肯定,我們大多數人都會同意,有可能用盡說明性DataContext來源親本自我上下文。然後,我們可能會訴諸綁定到父母Tag,然後使用元素綁定。所以來源可能是這樣的:元素綁定到摺疊的用戶控件是一個馬虎,廉價的伎倆?

<Grid.Tag> 
    <Binding Path="MyProperty" Source="{StaticResource MySource}" /> 
</Grid.Tag> 

當我們甚至不能做到這一點時會發生什麼?我的下一個馬虎的技巧是使用一個倒塌UserControl元素:

<UserControl 
    x:Name="MySloppyControl" 
    DataContext="{StaticResource YetAnotherSourceInThisCrazyGrid}" 
    Foreground={Binding CrazyForegroundColor} 
    Visibility="Collapsed" /> 

現在我可以這樣做:

<Grid.Resources> 
    <Style TargetType="{x:Type TextBox}"> 
     <Setter Property="Foreground" Value="{Binding CrazyForegroundColor, ElementName=MySloppyControl}" /> 
    </Style> 
</Grid.Resources> 

假設我充分解釋這一點,這是倒塌UserControl模式被誤導?

+0

您能舉一個「用完聲明式DataContext資源」的例子嗎?我似乎無法理解這一點。 – Vlad 2010-03-03 23:26:20

+0

讓我們忘記DataContext的「用完」,因爲你的問題意味着你從來沒有遇到過這個問題。對你而言,更有用的問題可能是'你有沒有使用XAML中的'UserControl'元素來處理任何*原因?順便說一下,這個問題是*不*詢問你是否建立了一個基於'UserControl'的自定義類型---我指的是*在你的XAML代碼中直接*寫'UserControl'。 – rasx 2010-03-04 00:13:57

回答

3

不是我自己沒有做過,但我必須說「是」 - 這種模式是錯誤的。

在那些我選擇這樣做我的代碼少數情況下是這樣的:

<Control x:Name="Whatever" DataContext="..." /> 
<Control x:Name="SomethingElse" DataContext="..." /> 

由於控制在默認情況下看不見這個acheives用更少的代碼相同的效果。

說了這麼多,讓我解釋一下爲什麼我認爲這種做法是錯誤的:

WPF是所有關於綁定到數據。如果您有一些要綁定的數據,它可能是模型的一部分(或視圖模型),也可能是外部的。如果它是模型(或視圖模型)的一部分,並且模型的結構已定義良好,則應該可以通過當前的DataContext訪問它。另一方面,如果它是靜態的,你應該能夠直接從目標訪問它。

例如,假設您想使用模型中的所有可能的WidgetType來填充ComboBox。如果您的模型構建良好的結合可以是簡單的:

<ComboBox ItemsSource="{Binding DataSet.AllWidgetTypes}" /> 

這裏假設你的組合框的DataContext的是一個「小部件」和「部件」有一個「數據集」屬性,讓到其他接入相關數據。或者,如果可用類型的列表可能會根據Widget的其他詳細信息而更改,則綁定可能只是{Binding AppliableWidgetTypes}

在您調用它時可能需要「單獨的DataContext」的其他情況是在引用靜態對象時(例如通過x:Static或StaticResource)。在這些情況下,有一個更好的方法來做到這一點:設置Binding.Source。它看起來像這樣:

Text="{Binding DefaultFontSize,Source={x:Static ApplicationProperties.Instance}}" 

或本

Text="{Binding PropertyName,Source={StaticResource ResourceContainingProperty}}" 

如果你的動機是爲了避免創建一個視圖模型多個模型對象相結合,使用C#anonymoust類型構造,窮人的視圖模型。例如:

DataContext = new { something = 123, whatever = "Test" }; 

另一種常見模式是在控件上創建屬性並使用ControlTemplate和TemplateBinding綁定到它們。

這留下了一個最後的情況,那就是當你真的想要一個共享的值,並且你根本不需要代碼隱藏。在這種情況下,我實際上已經提前使用了前面所示的隱形<Control>。所以在極少數情況下可能適用。