2011-09-12 3 views
16

UserControls를 다른 ListBox의 예제처럼 DataTemplates와 같은 페이지 나 창과 같은 UserControls에서 다시 사용하고 싶습니다. 모든 것이 MVVM입니다.ListBox 내 DataTemplate으로 UserControl

간단한 개체 "카드"를 표시하려면 "CardControl"이라는 UserControl이 있습니다. 카드에는 두 개의 속성, "ID"및 "CardImage"가 있습니다. 컨트롤 DataContext는 XAML을 통해 설정됩니다. 이 UserControl을 VS 또는 Blend에서 열면 해당 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에 대한 기사의 톤을 읽은 후/I가 여전히 작동하지 않았다 바인딩. 이 전체 계층 적 USerControls/DataContexts가 어떻게 가장 깨끗한 방식으로 수행됩니까?

답변

13

합니다. Item이 DataContext로 설정되고 ItemTemplate이 템플릿으로 설정됩니다. DataContext는 상속하므로 DataTemplate의 Card 인스턴스가 이미 있으므로 명시 적으로 설정하지 않아도됩니다.

이 경우 CardControl이 설정되었으므로 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

예에서 UserControl데이터 콘텍스트이 현재 선택된 카드가됩니다. UserControl으로 이동하고 다른 UIElement과 같은 자식 컨트롤은 부모 컨트롤의 DataContext을받습니다.

이 작동합니다 :

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

을 CardControl은 여기서 유추 ListBoxItem의이 항목 소스의 각 항목에 대해 작성됩니다 ListBox 컨트롤에 대한

<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 항목 및 ID에 대한 템플릿으로 사용되는 볼 수 있으며 이미지가 올바르게 표시됩니다.

게다가 ViewModel에서 정의한 다른 속성에 바인딩 할 수 없는데 왜 ID와 이미지를 표시 할 수 있는지 궁금해했습니다.

오늘 나는 DataContext hierachy에 대한 흥미로운 기사를 발견했습니다. ListBox 안에있는 DataContext는 ListBox가있는 페이지와 같은 DataContext가 아니라고합니다. 그렇게 보지 못했기 때문에 전에 언급 한 것처럼 DataContext를 설정해야한다고 생각했습니다. 문제. 이제 모든 속성에 바인딩 할 수 있습니다. http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/