UserControl как DataTemplate внутри ListBox - PullRequest
       35

UserControl как DataTemplate внутри ListBox

17 голосов
/ 12 сентября 2011

Я хочу повторно использовать свои UserControls в других UserControls, таких как страница или окно, как DataTemplates, в этом примере внутри ListBox.Все это MVVM.

У меня есть UserControl под названием "CardControl" для отображения простого объекта "Card".Карта имеет два свойства: «ID» и «CardImage».Элементы управления DataContext устанавливаются через XAML.Если я открываю этот UserControl в VS или Blend, он показывает мне фиктивную карту, которую я определил в соответствующей ViewModel.

Теперь у меня есть другой UserControl, называемый "CardSetControl", который должен отображать коллекцию карт.Таким образом, у ViewModel есть одно свойство типа ObservableCollection , называемое «Cards».

Вот код:

<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 / Binding я до сих порне заставить его работать.Как все это иерархическое действие USerControls / DataContexts сделано наилучшим образом?

Ответы [ 3 ]

15 голосов
/ 12 сентября 2011

В вашем примере DataContext из UserControl будет текущей выбранной картой. Он входит в 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>
13 голосов
/ 12 сентября 2011

Для элемента управления ListBox предполагаемый элемент ListBoxItem создается для каждого элемента в источнике элементов. Item установлен как DataContext, а ваш ItemTemplate установлен как шаблон. Поскольку DataContext наследуется, вам не нужно явно устанавливать его, потому что это уже экземпляр Card в вашем DataTemplate.

В этом случае вам не нужно устанавливать 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> 

Должно работать на вас.

1 голос
/ 15 сентября 2011

Спасибо за ваши ответы, но я узнал, что моя проблема была еще одной, о которой я упоминал.Если вы делаете это так, как вы описали, я вижу, что мои UserControls (CardControl) используются в качестве шаблона для элементов ListBox, а ID и изображение отображаются правильно.

Кроме того, мне всегда было интересно, почему могут быть идентификаторы и изображения.отображается, пока я не могу связать с некоторыми другими свойствами, которые я определил в ViewModel.

Сегодня я нашел интересную статью об иерархии DataContext.Там сказано, что DataContext внутри ListBox НЕ является тем же DataContext, что и на странице, на которой находится ListBox. Я этого раньше не видел, поэтому подумал, что должен установить DataContext каким-то образом, как я упоминал ввопрос.Теперь я могу связать все свойства.

Вот статья: http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/

...