2011-09-12 7 views
16

UserControlsを、この例ではListBox内のDataTemplatesとしてページやウィンドウなどの他のUserControlsで再利用したいとします。すべてがMVVMです。ListBox内のDataTemplateとしてUserControl

私は単純なオブジェクト "カード"を表示するために "CardControl"と呼ばれるUserControlを持っています。カードには「ID」と「CardImage」の2つのプロパティがあります。コントロールDataContextは、XAMLを介して設定されます。このUserControlをVSまたはBlendで開くと、対応するViewModelで定義したダミーのカードが表示されます。

私はカードのコレクションを表示する必要があります "CardSetControl"と呼ばれる別のUserControlがあります。したがって、ViewModelにはObservableCollectionタイプの1つのプロパティー「<カード>」が「カード」と呼ばれています。ここで

はコードです:

<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

を。 ItemがDataContextとして設定され、ItemTemplateがテンプレートとして設定されます。 DataContextは継承しているので、明示的に設定する必要はありません。これは、すでにDataTemplateのCardのインスタンスであるためです。

この場合、CardControlが設定されているため、DCをCardControlに設定する必要はありません。

<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である場合:推論ListBoxItem項目ソースの各アイテムのために作成されるリストボックスコントロールについて

<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

このようにして、モデル(カード)はDataContextとしてユーザーコントロールに渡されます。ビューモデルを使用するためにそのユーザーコントロールを使用したい場合はどうすればよいですか?このモデルをビューモデルに渡してビューモデルをコントロールのビューにバインドするにはどうすればよいですか? –

+0

@OndrejJanacek:UserControlsは、独自のビューモデルを持つように設計するべきではありません。彼らは、ユーザーが自分のビューモデルにバインドする公開可能なバインディング可能なプロパティをそのサーフェスに配置する必要があります。この回答は、ベストプラクティスよりもOPの方がよりよく形成されています。/ – Will

1

お返事ありがとうございますが、私の問題は私が言及したもう一つの問題であることが分かりました。私のUserControls(CardControl)がListBox ItemsとIDのテンプレートとして使用され、Imageが正しく表示されることがわかりました。

私はViewModelで定義した他のいくつかのプロパティにバインドすることができないが、IDとImageを表示できる理由について私はいつも思っていた。

今日私はDataContext hierachyについて興味深い記事を見つけました。 ListBox内のDataContextは、ListBoxが入っているページと同じDataContextではないと言われています。その前に私はそれを見ていませんでしたので、私が何らかの方法でDataContextを設定する必要があると思いました質問。これで、すべてのプロパティにバインドできます。ここで

記事です: http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/

関連する問題