Как настроить ItemsControl WPF для отображения каждого элемента в уникальном месте?

Я создаю программу для блэкджека и в настоящее время работаю над отображением рук.

У меня есть PlayerSeat UserControl, внутри которого есть ItemsControl для отображения карточек. Как и в обычной игре в блэкджек, карты (в моем случае изображения) накладываются друг на друга. Различные игровые действия (Split, Double Down и т.д.) должны менять расположение карт на экране. Свойство ItemSource элемента управления ItemsControl является свойством "ObservableCollection<Card> Hand" в ViewModel моего проигрывателя. Объекты Card содержат BitmapSources с изображениями Card.

Я просмотрел несколько веб-страниц (см. конец поста) в поисках способов добиться того, чего я хочу. Я ищу способ сделать один из двух вариантов.

  1. (Предпочтительно) Укажите макет для каждого «режим руки» (Разделить, Удвоить и т. д.) и указать, где каждый индекс руки (OC<Card>) должен быть размещен по порядку. Например, для первой карты в раздаче поместите элемент управления Image с привязкой Source к Hand[0].CardImage в (X1, Y1), затем поместите Hand[1] Image в (X2, Y2) и так далее. Это было бы оптимально настроить, установив какое-то связанное свойство шаблона (для переключения между режимами руки) в ItemsControl.

  2. (Запасной вариант) Отображение всех элементов управления Image с привязкой к их исходным свойствам. Привяжите свойства Top/Left этих изображений к Hand[0].Top/Left и выполните вычисления размещения в классе Hand.

Я не из тех, кто спрашивает, не изучив вопрос сам. Похоже, мне нужно использовать ItemsPanelTemplate со StackPanel, но я понятия не имею, с чего начать. Ключ в том, чтобы изображения перекрывались и размещались там, где я хочу. Любой свет, который вы могли бы пролить на мою проблему, был бы полезен.

Ссылка: http://drwpf.com/blog/itemscontrol-a-to-z/ (в частности, "ItemsControl: "P" для панели")


person Caesar Kabalan    schedule 07.02.2011    source источник


Ответы (2)


Не могли бы вы использовать Canvas в качестве ItemsPanelTemplate? Что-то типа:

<ItemsControl ItemsSource="{Binding Hand}">
  <ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <Canvas />
    </ItemsPanelTemplate>
  </ItemsControl.ItemsPanel>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Image Source="{Binding Image}" Width="{Binding ImageWidth}" Height="{Binding ImageHeight}" />
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <ItemsControl.ItemContainerStyle>
    <Style>
      <Setter Property="Canvas.Left" Value="{Binding ImageX}" />
      <Setter Property="Canvas.Top" Value="{Binding ImageY}" />                    
    </Style>
  </ItemsControl.ItemContainerStyle>
</ItemsControl>

Это предполагает, что у вас есть свойства позиции в вашем классе Hand. Если это не подходит, вы можете создать оболочку HandViewModel, которая содержит экземпляр Hand и эти дополнительные свойства X, Y, которые используются только для целей отображения. Возвращаемые значения для этих свойств могут меняться в зависимости от вашего текущего «ручного режима».

person devdigital    schedule 07.02.2011

Ваша модель представления не должна вообще ничего знать о физическом положении ваших карт, если вы правильно спроектировали свое представление. Вот довольно простой пример. Стили по умолчанию, которые я создал для TextBlock и Border, определяют, насколько они велики и (через отрицательное поле) как они перекрываются, когда они сложены вместе. ItemsControl использует горизонтальный StackPanel для макета.

Если вы примете этот подход, вы можете разместить элементы управления элементами там, где они должны быть расположены в представлении (я бы использовал некоторую комбинацию стыковочных панелей и полей для организации этого), и либо иметь другую коллекцию в вашей модели представления для каждого элемента управления для привязки.

Возможно, это немного сложнее, но вы также можете иметь единую коллекцию объектов карты и связать каждый ItemsControl ItemsSource с CollectionView, который фильтруется по некоторому свойству карты. Хорошая вещь в том, что вы можете «перемещать» карту из одного места в другое, просто изменяя значение этого свойства.

В любом случае вы увидите, что как только вы сделаете элементы управления ответственными за управление макетом их содержимого, вы сможете свободно перемещать их в представлении, не касаясь модели представления.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Page.Resources>
  <Style TargetType="TextBlock">
    <Setter Property="Height" Value="150"/>
    <Setter Property="Width" Value="100"/>
  </Style>
   <Style TargetType="Border">
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Background" Value="Lightgray"/>
    <Setter Property="Margin" Value="0, 0, -80, 0"/>
    </Style>
   </Page.Resources>
  <StackPanel>  
    <ItemsControl>
      <ItemsControl.ItemsPanel>
       <ItemsPanelTemplate>
        <StackPanel Orientation="Horizontal"/>
       </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
      <Border>
       <TextBlock Text="Foo"/>
      </Border>
      <Border>
       <TextBlock Text="Bar"/>      
      </Border>
      <Border>
       <TextBlock Text="Baz"/>      
      </Border>
    </ItemsControl>
  </StackPanel>
</Page>
person Robert Rossney    schedule 08.02.2011