Что именно делает Panel.IsItemsHost? - PullRequest
32 голосов
/ 18 мая 2010

Я не могу найти хорошую документацию для присоединенного свойства Panel.IstItemsHost. Я вижу множество примеров того, как люди настраивают его в шаблоне ItemsContainer для ItemsControl, но недокументирование в MSDN не объясняет, почему или какие преимущества дает свойство настройки. Я построил множество контейнеров, которые НЕ устанавливают это свойство, но еще не заметили каких-либо побочных эффектов.

Ответы [ 3 ]

36 голосов
/ 18 мая 2010

Скажем, у меня есть ItemsControl.Я хочу использовать пользовательскую панель, которая перемещает элементы во время прокрутки;это называется SwoopPanel.Теперь, как мне сказать ItemsControl использовать мою SwoopPanel для хранения создаваемых шаблонов?

Самый быстрый способ - установить ItemsPanel на ItemsControl:

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
      <lol:SwoopPanel />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Однако иногдане работает для васВозможно, вы захотите настроить представление SwoopPanel в пользовательском интерфейсе, и единственный способ обойти это - изменить шаблон элемента управления ItemsControl.Теперь вы можете добавить SwoopPanel непосредственно в шаблон элемента управления и, используя свойство, пометить его как ItemsHost, чтобы ItemsControl поместил все созданные им шаблонные элементы.

<Style TargetType="ItemsControl">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ItemsControl">
        <Border CornerRadius="5">
          <ScrollViewer VerticalScrollBarVisibility="Hidden">
            <lol:SwoopPanel IsItemsHost="True"/>
          </ScrollViewer>
        </Border>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Вам нужно сделать это одинтак или иначе?Нет. Является ли один более выгодным, чем другой?Что ж, второй способ позволяет вам лучше контролировать пользовательский интерфейс, первый способ проще.Выбирай, правда.Лично я никогда не делал это вторым способом, но я думаю, что есть пара мест, где это может быть полезно.

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

См. http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.90).aspx

По сути, этот пост говорит о том, что если вы заменяете ControlTemplate элемента ListBox и хотите создать новый макет, установите IsItemsHost = true на некоторой панели, например, StackPanel. Затем любые элементы в ListBox будут автоматически добавлены как дочерние элементы StackPanel. Если ориентация ListBox является горизонтальной, то ListBox будет горизонтальной.

Другой способ - установить для свойства ItemsPanel объекта ListBox значение ItemsTemplate, и в этом шаблоне у вас будет StackPanel. В этом случае элементы ListBox будут добавлены к дочерним элементам StackPanel, как и в первом случае. Однако вам не нужно устанавливать IsItemsHost = true, это не будет иметь абсолютно никакого эффекта. Это сделано для вас тем, что вы устанавливаете свойство ItemsPanel.

3 голосов
/ 23 января 2019

Больше объяснений, пожалуйста!

Хотя все вышеприведенные ответы являются технически правильными, я чувствую, что они не иллюстрируют, как IsItemsPanel соотносится с ControlTemplate и наличием (или отсутствием) ItemsPresenter и соответствующего свойства ItemsPanel, которое оно использует. Этот ответ попытается пролить свет на эти вещи и, надеюсь, уточнить, когда вы должны или не должны использовать каждый из них.

ItemsControls, Panels and IsItemsHost, Oh my!

ItemsControl - это просто элемент управления, отображающий коллекцию элементов. Для этого он сначала генерирует ItemContainer для каждого из этих элементов, затем вставляет эти контейнеры в (или удаляет их) из определенной панели «хоста» и, наконец, эта панель размещает контейнеры для отображения.

Специальная панель, используемая для размещения контейнеров, является первой панелью в иерархии ItemControl, для которой свойство IsItemsHost имеет значение True. Есть два способа указать, какая это панель:

  1. Вставив ItemsPresenter в ControlTemplate, затем установив свойство ItemsPanel, или ...
  2. Вставив Panel непосредственно в ControlTemplate и явно указав для IsItemsHost значение «Истина».

Но что вы используете и почему? Читайте дальше, чтобы узнать!

ItemsPresenter - «Имей свой путь!»

В типичном ControlTemplate для ItemsControl, таком как ListBox, шаблон указывает ItemsPresenter где-то внутри него. Вот упрощенная выдержка, показывающая, как она используется:

<Border x:Name="Bd"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}"
    Background="{TemplateBinding Background}"
    Padding="1" SnapsToDevicePixels="true">

    <ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
    </ScrollViewer>
</Border>

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

Итак, если в шаблоне не определена панель, откуда она взялась? Вот тут и появляется свойство ItemsPanel. Как следует из названия, это свойство определяет, какая панель будет использоваться для размещения и размещения элементов. Однако не указано, где эта панель появляется в ControlTemplate.

Это возвращает нас к ItemsPresenter. Короче говоря, это местозаполнитель, который по сути говорит: «Когда установлено свойство ItemsPanel, я вставлю эту панель сюда и автоматически установлю для IsItemsHost значение« True »."

Преимущество использования ItemsPresenter в шаблоне для вашего ItemsControl состоит в том, что вы облегчаете потребителям вашего контроля замену панели без необходимости повторной настройки шаблона. весь ваш контроль.

IsItemsHost - «Мой путь или шоссе!»

Однако что, если вы не хотите, чтобы кто-то мог изменить вашу панель, потому что ваш контроль зависит от какой-то реализации пользовательской панели, и что-то еще нарушит функциональность? В этом случае вы не используете ItemsPresenter в своем шаблоне. Вместо этого вам нужно указать точную панель, которую вы хотите использовать.

Здесь IsItemsHost свойство вступает в игру. При установке на панели в ControlTemplate, он сообщает, что ItemsControl должен использовать эту конкретную панель для размещения сгенерированных контейнеров, независимо от того, для чего установлено ItemsPanel.

Вот тот же пример, что и выше, но вместо ItemsPresenter он жестко кодирует SpecializedPanel для разметки элементов. Мы указываем, что это панель, которую мы хотим использовать для размещения элементов, установив для свойства IsItemsHost значение «True».

<Border x:Name="Bd"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}"
    Background="{TemplateBinding Background}"
    Padding="1" SnapsToDevicePixels="true">

    <ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
        <SpecializedPanel IsItemsHost="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
    </ScrollViewer>
</Border>

В этом случае, поскольку шаблон не использует ItemsPresenter и вместо этого непосредственно включает в себя панель с IsItemsHost, установленной в «Истина», пользователь не может изменить эту панель за исключением полностью замена всего ControlTemplate. Установка свойства ItemsPanel будет по существу игнорироваться.

Приносить все домой ...

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

Если вместо этого вы хотите заблокировать панель, которую ваш элемент управления использует в этом ControlTemplate, не используйте ItemsPresenter. Вместо этого прямо укажите, какую панель вы хотите использовать для размещения своих элементов, и установите для свойства IsItemsHost значение «True»

.

Примечание: Технически существует третий сценарий, который, возможно, более распространен: вы не автор контрольной программы, создающий что-то, что будет использоваться другими, а скорее просто переписываете ItemsControl (как, скажем, ListBox ) для использования в вашем собственном приложении.

В этом случае, поскольку вам, скорее всего, не придется беспокоиться о других нижестоящих, нуждающихся в замене панели, вполне нормально указать панель непосредственно в вашем шаблоне (опять же, установив ее IsItemsHost true). В этом случае использование ItemsPresenter и связанного с ним свойства ItemsPanel просто добавит ненужную сложность без какой-либо реальной выгоды.

Надеюсь, это проясняет, что именно происходит.

...