2011-09-12 102 views
16

我想在其他UserControls中重用我的UserControls,如頁面或窗口作爲DataTemplates,在本例中是一個ListBox。一切都是MVVM。用戶控件作爲ListBox中的DataTemplate

我有一個名爲「CardControl」的UserControl來顯示一個簡單的對象「Card」。卡有兩個屬性,「ID」和「CardImage」。控件DataContext通過XAML進行設置。如果我在VS或Blend中打開這個UserControl,它會顯示我在相應的ViewModel中定義的虛擬卡。

現在我有另一個名爲「CardSetControl」的UserControl,它應該顯示卡的集合。因此,ViewModel有一個類型爲ObservableCollection的屬性<卡片>稱爲「卡片」。

下面是代碼:

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 

     <!-- WORKING, but not what i want --> 
     <TextBlock Text="{Binding ID}" /> // would display ID of Card 
     <Image Source="{Binding Image}" /> // would display Image of Card 

     <!-- NOT WORKING, but this is how i want it to work --> 
     <UserControls:CardControl DataContext="{Binding "Current listbox item as DataContext of CardControl???"}" /> 

     </StackPanel> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

閱讀約MVVM和DataContext的文章噸後​​/綁定我仍然沒有得到它的工作。這整個分層的USerControls/DataContexts事情如何完成最好的清潔方式?

回答

13

對於推斷ListBoxItem的是在項目源的每個項目創建的ListBox控件。該項目被設置爲DataContext並且您的ItemTemplate被設置爲模板。由於DataContext繼承,所以您不必顯式設置它,因爲它已經是DataTemplate中Card的實例。

對於這種情況,您不必在CardControl上設置DC,因爲它是爲您設置的。

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 

     <!-- WORKING, but not what i want --> 
     <TextBlock Text="{Binding ID}" /> // would display ID of Card 
     <Image Source="{Binding Image}" /> // would display Image of Card 

     <!-- NOT WORKING, but this is how i want it to work --> 
     <UserControls:CardControl /> 

     </StackPanel> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

應該爲你工作。

14

在您的示例中,UserControlDataContext將是當前選定的卡。它流入UserControl,其子控件像其他任何UIElement一樣接收其父控件的DataContext

這會工作:

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <UserControls:CardControl /> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

其中CardControl是:

<UserControl x:Class="MySolution.CardControl" 
      OtherProperties="Not shown to keep this example small"> 
     <StackPanel> 
     <TextBlock Text="{Binding ID}" /> 
     <Image Source="{Binding Image}" /> 
     </StackPanel> 
</UserControl> 
+0

意志,我道歉我基本放棄了確切相同的答案你。我應該在下次回答之前刷新頁面;) –

+0

這樣一個模型(Card)作爲DataContext傳遞給用戶控件。如果我想讓該用戶控件使用其視圖模型怎麼辦?我應該如何將接收到的模型傳遞給視圖模型並將視圖模型綁定到控件的視圖? –

+0

@OndrejJanacek:UserControls不應該被設計爲擁有自己的視圖模型。他們應該在表面上擁有公共可綁定屬性,用戶將綁定到他們自己的視圖模型。對於OP而言,這個答案比最佳實踐更適合:/ – Will

1

謝謝你的回答,但我發現我的問題是我提到的另一個問題。如果按照您描述的方式進行操作,我可以看到我的UserControls(CardControl)被用作ListBox Items的模板,並且ID和Image正確顯示。

除此之外,我總是想知道爲什麼可以顯示ID和圖像,而我無法綁定到我在ViewModel中定義的其他屬性。

今天我發現了一篇關於DataContext hierachy的有趣文章。據說在ListBox中的DataContext與在ListBox中的頁面不是相同的DataContext。我之前沒有看到,所以我想我必須以某種方式設置DataContext,就像我在題。現在我可以綁定到所有屬性。

下面是文章: http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/

相關問題