Panel.IstItemsHost
附加属性用于什么目的?
我看到很多人在 ItemsControl
的 ItemsContainer
模板上设置它,但是MSDN上的非官方文档并没有解释为什么或者设置这个属性会带来哪些优势。
Panel.IstItemsHost
附加属性用于什么目的?
我看到很多人在 ItemsControl
的 ItemsContainer
模板上设置它,但是MSDN上的非官方文档并没有解释为什么或者设置这个属性会带来哪些优势。
假设我有一个ItemsControl。我想使用一个自定义面板,在滚动时将项目向内和向外扫过来;它被称为SwoopPanel。现在,我该如何告诉ItemsControl使用我的SwoopPanel来包含它创建的模板?
快速的方法是在ItemsControl上设置ItemsPanel:
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<lol:SwoopPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
然而,有时候这并不适用于你。也许你希望自定义SwoopPanel在UI中的呈现方式,而唯一的解决方法就是更改ItemsControl的控件模板。现在你可以直接将SwoopPanel添加到控件模板中,并使用属性将其标记为ItemsControl将放置所有模板化项的ItemsHost。
<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>
虽然上面的所有答案在技术上都是正确的,但我觉得它们没有说明IsItemsPanel
如何与ControlTemplate
以及ItemsPresenter
的存在(或不存在)以及它使用的相应ItemsPanel
属性相关。本答案将尝试阐明这些问题,并希望澄清何时应该或不应该使用每个选项。
ItemsControl
只是一个显示项目集合的控件。它首先生成单独的容器*来表示项目的可视化,然后将这些容器交给特定的面板进行屏幕展示。随着项目的添加或删除,ItemsControl
会根据需要向面板添加或删除相应的容器。
* 注意:如果一个项目已经是容器类型的实例(由ItemsControl
的IsItemItsOwnContainer覆盖确定),即您将ListBoxItem
实例添加到ListBox
的Items
集合中,则该项目将直接传递为其自己的容器。
<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</Border>
ItemsPresenter
,放在了ScrollViewer
内。然而,您没有看到实际用于布局项目的面板。ItemsPanel
属性发挥作用的地方。顾名思义,此属性定义将用于托管和布置项目的面板。但它并不说该面板出现在ControlTemplate
的哪个位置。ItemsPresenter
。简而言之,它是一个占位符,基本上表示“当设置ItemsPanel
属性时,我会自动将该面板插入到这里,并将其IsItemsHost
设置为True
。”ItemsControl
模板中的ItemsPresenter
的优点是,您使消费者轻松替换面板,而无需完全重新设计整个控件。ItemsPresenter
。相反,您需要指定要使用的确切面板。<Border x:Name="Bd"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<SpecializedPanel name="PART_MainPanel" IsItemsHost="True" />
</ScrollViewer>
</Border>
ItemsPresenter
,而是直接包含一个面板,并将其IsItemsHost
设置为True
,因此用户无法更改该面板,除非完全替换整个ControlTemplate
。(如前所述,ItemsPanel
属性被忽略。)ItemsPresenter
定义您的ItemsControl
的模板。还要确保在模板中设置ItemsPanel
属性以指定默认面板。ControlTemplate
中使用ItemsPresenter
。相反,在模板中直接指定要使用的特定面板,然后将其IsItemsHost
属性设置为True
。请参见http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.90).aspx
本质上,这篇文章说明了如果你正在替换ListBox的ControlTemplate并希望使用新布局,则需要在某个面板(例如StackPanel)上设置IsItemsHost=true。那么ListBox中的任何项都将自动添加为StackPanel的子项。如果ListBox的方向是水平的,则ListBox将是水平的。
另一种方法是将ListBox的ItemsPanel属性设置为一个ItemsTemplate,在该模板中您有一个StackPanel。在这种情况下,ListBox项将像第一种情况一样添加到StackPanel的子项中。但是,您不需要设置IsItemsHost = true,它完全没有影响。这是由于您设置了ItemsPanel属性。
IsItemsHost="True"
而不是ItemsPresenter
的另一个原因是你可以将其作为模板部件进行访问。 - Mitch