Почему ItemsControl не использует мой ItemTemplate? - PullRequest
9 голосов
/ 02 октября 2010

Я могу использовать ItemTemplate внутри ItemsControl для отображения элементов в определенном формате. Однако, если один из элементов в ItemsControl оказывается, скажем, TextBox, этот TextBox отображается, а не экземпляр ItemsTemplate. Из того, что я могу сказать, это верно для любого FrameworkElement. Это предполагаемое поведение для ItemsControl или я что-то делаю неправильно?

Пример:

<ItemsControl>
  <ItemsControl.ItemTemplate>
    <DataTemplate>
      <Grid Margin="5">
        <Rectangle Fill="Blue" Height="20" Width="20" />
      </Grid>
    </DataTemplate>
  </ItemsControl.ItemTemplate>
  <ItemsControl.Items>
    <sys:Object />
    <TextBox />
    <sys:Object />
    <Rectangle Fill="Red" Height="20" Width="20" />
  </ItemsControl.Items>
</ItemsControl>

Я ожидал, что это покажет четыре синих прямоугольника. Я думал, что каждый раз, когда ItemTemplate был определен, каждый элемент в коллекции отображается как экземпляр шаблона. Однако в этом случае отображается следующее: синий прямоугольник, за которым следует TextBox, за которым следует синий прямоугольник, за которым следует красный прямоугольник.

Ответы [ 2 ]

14 голосов
/ 02 октября 2010

ItemsControl имеет защищенный элемент IsItemItsOwnContainerOverride, который передает объект из коллекции элементов и возвращает true, если этот объект может быть добавлен непосредственно на панель элементов без созданного контейнера (и, следовательно, с помощью шаблона).

Базовая реализация возвращает true для любого объекта, производного от UIElement.

Чтобы получить поведение, которое вы ожидаете, вам нужно унаследовать от ItemsControl и переопределить этот метод, чтобы он всегда возвращал false. К сожалению, это еще не конец. Реализация по умолчанию PrepareContainerForItemOverride по-прежнему не назначает ItemTemplate контейнеру, если элемент является UIElement, поэтому вам также необходимо переопределить этот метод: -

    protected override bool IsItemItsOwnContainerOverride(object item)
    {
        return false;
    }


    protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
    {
        base.PrepareContainerForItemOverride(element, item);
        ((ContentPresenter)element).ContentTemplate = ItemTemplate;
    }
2 голосов
/ 02 октября 2010

Я просто спекулирую здесь, но могу поспорить, что это поведение живет внутри ItemContainerGenerator.Могу поспорить, что ItemContainerGenerator смотрит на предмет, и если это UIElement, он говорит: «круто, контейнер предмета сгенерирован, я просто верну его», а если это не так, он говорит: «Ялучше создать контейнер для этого предмета. Где же DataTemplate? "

...