2012-10-21 50 views
3

我使用MVVM模式,所以我自己的控件包含View和ViewModel。
ViewModel與通過DataContext屬性查看連接。這會造成綁定問題。爲什麼?通過MVVM模式創建UserControl - DataContext並綁定到父項

假設這種情況:
我創建了新的用戶控件 - 例如 - 「SuperTextBox」。它有一個屬性「SuperValue」。
現在我做這樣的事情:

<Window> 
    <Window.DataContext> 
     <vm:WindowViewModel/> 
    </Window.DataContext> 

    <local:SuperTextBox SuperValue="{Binding Test}"/> 
</Window> 

我認爲「結合的過程」與Window.DataContext.Test加入SuperTextBox.SuperValue,但沒有,「綁定過程」加入SuperTextBox.SuperValue與SuperTextBox.DataContext。考什麼對我來說是不自然的,誤導性的。

像其他控件「文本框」我可以用上面的方法使用,因爲它們沒有自己的DataContext。

如何使用MVVM模式來創建用戶控件保持自然的結合(到父級控件的DataContext)?

編輯:

我得到了很多答案如何結合的父母,但我知道這點。問題是 - 如何通過MVVM patern(具有ViewModel)創建UserControl並保持自然綁定 - 默認爲父級DataContext。

我想有ViewMoldel而且還可以像這樣綁定:

<local:SuperTextBox SuperValue="{Binding Test}"/> 

這可能嗎?

+0

它可能當你創建一個真正的用戶控件與依賴性屬性,如我發佈。但我會編輯我的答案,以顯示另一種「不自然」的方式:) – blindmeis

回答

1

我感到奇怪的是回答我的問題,但...
在我自己控制,我沒有類似的東西:

<UserControl> 
    <Grid> 
     <Grid.DataContext> 
      <vm:UserControlViewModel /> 
     </Grid.DataContext> 
     // here realy code of control 
    </Grid> 
</UserControl> 

現在我可以用「自然」結合控制的控制外。 :)

1

你需要「查找」它的窗口祖先的datacontext。您的綁定將如下所示:

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"> 
+0

謝謝,但我知道。 :)我需要的信息,而不是「模式和實踐」,通過MVVM模式創建UserControl。我可以使用MVVM,並仍然具有像「TextBox」控件一樣的正常/自然聯合? – Never

+0

對此,沒有什麼不自然的。您必須對任何具有來自其ItemsSource中單個項目的datacontext的控件元素執行相同的操作。例如,如果要將ListViewItem的可見性綁定到viewmodel中的值,但ListView具有ItemsSource集,則必須使用此方法進行綁定。 –

2

所有綁定應用於任何control always first look for the binding in its DataContext。如果DataContext沒有爲控件設置,那麼它walks up the Visual Tree直到其父,除非它找到DataContext。

即使你設置你的文本框比窗口的DatContext的一些不同的價值DataContext,它總是會尋找物業Test在那個特定的DataContext上,而不是Window's DataContext

<TextBox> 
    <TextBox.DataContext> 
     <vm:ViewModelForTextBox/> 
    </TextBox.DataContext> 
    <TextBox.Text> 
     <Binding Path="Test"/> 
    </TextBox.Text> 
</TextBox> 

現在,XAML將尋找Test財產ViewModelForTextBox類,而不是WindowViewModel類,如果在ViewModelForTextBox類,binding will fail silently沒有找到Test財產,不會仰望窗口的DataContext類。

如果你仍然想設置的DataContext爲您的自定義用戶控件,但仍希望綁定到父(窗口)的DataContext,你必須使用你的綁定RelativeSource MarkupExtension這樣的 -

<local:SuperTextBox SuperValue="{Binding Path=DataContext.Test, 
           RelativeSource={RelativeSource Mode=FindAncestor, 
               AncestorType={x:Type Window}}}"> 

參考到MSDN文章here以獲得更多的說明。

1

你應該發佈你的SuperTextBox代碼,因爲有你的錯誤。

通常你創建一個帶有依賴項屬性的用戶控件 - 在你的情況下是「SuperValue」 - 現在最重要的是你不會將你的SuperTextBox的datacontext設置爲self。

你必須使用你的SuperTextBox內的ElementName綁定來綁定到「SuperValue」

<SuperTextBox x:Name="uc"> 
    <TextBox Text="{Binding ElementName=uc, Path=SuperValue}/> 
</superTextBox> 

如果你這樣做這樣 - 你

<local:SuperTextBox SuperValue="{Binding Test}"/> 

應該工作,應該與待測物業你的vm:WindowViewModel。那就是只有的方式來寫上面的綁定。

編輯:如果你想爲你的用戶控件創建一個viewmodel,比如說SuperTextViewmodel。那麼它會有一個屬性「SuperValue」。現在你不能設置datacontext兩次,所以我建議你必須添加一個屬性到你的類型爲SuperTextViewmodel的WindowViewmodel並處理你想要的屬性。

您結合這個樣子的

<local:SuperTextBox DataContext="{Binding MySuperTextViewmodelInstanceOnWindowViewmodel}"/> 

我會用我的答案的第一部分去:)我總是說一個觀點需要一個視圖模型,但一個用戶控件依賴屬性。

+0

感謝您的答案,但是當我使用MVVM模式創建UserControl時,我必須擁有(或者我想擁有)ViewModel。所以要將ViewModel注入到視圖中,我必須使用DataContext使綁定不自然。我的問題是,我怎樣才能避免這種情況 - 我可以以另一種方式加入ViewModel(這不會損壞綁定)? – Never

相關問題