Почему ItemsControl не использует мой ItemTemplate?

Я могу использовать 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, за которым следует синий прямоугольник, за которым следует красный прямоугольник.

 Golvellius27 нояб. 2013 г., 17:22
Отличный вопрос и отличный ответ Энтони, спасибо, ребята.
 Drew01 окт. 2010 г., 23:44
Я предполагаю, что это предполагаемое поведение и предназначено, чтобы позволить разработчикам возможность добавлять специальные одноразовые элементы управления использованием. Например, я мог бы использовать это для добавления Button в ComboBox, который очищает выделение, или я мог бы поместить TextBox в ListBox, который фильтрует коллекцию, указанную ItemsSource. Я хотел бы услышать, что у кого-то есть официальный ответ на это поведение, потому что я нашел его нелогичным при использовании ItemTemplate.

Ответы на вопрос(2)

но я бы поспорил, что это поведение, которое живет внутриItemContainerGenerator, Держу пари, чтоItemContainerGenerator смотрит на предмет, и если этоUIElement он говорит: «круто, контейнер элемента создан, я просто верну его», а если это не так, он говорит: «Я бы лучше сгенерировал контейнер для этого элемента.DataTemplate

Решение Вопроса

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;
    }
 Sheridan07 июн. 2019 г., 16:07
Мне не нужноPrepareContainerForItemOverride переопределить либо в .NET 4.
 Glenn Slayden18 мая 2015 г., 23:51
По состоянию на 2015 год они могли бы исправить вторую часть. С WPF в .NET 4.5.1, если я вернусьfalse заIsItemItsOwnContainerOverride, затем шаблон будет установлен для контейнера элемента.

Ваш ответ на вопрос