Panel.IsItemsHost 到底做了什么?
Panel.IstItemsHost
附加属性的用途是什么?
我看到很多人在 ItemsControl
的 ItemsContainer
模板上设置它的例子,但 MSDN 上的非文档并没有解释设置属性的原因或优势。
What is the Panel.IstItemsHost
attached property used for?
I see plenty of examples of people setting it on the ItemsContainer
template for an ItemsControl
, but the un-documentation over at MSDN does not explain why or what advantages setting property confers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
假设我有一个 ItemsControl。我想使用一个自定义面板,当您滚动时,该面板可以将项目快速进出;它称为 SwoopPanel。现在,我如何告诉 ItemsControl 使用我的 SwoopPanel 来包含它创建的模板?
快速方法是在 ItemsControl 上设置 ItemsPanel:
但是,有时这对您不起作用。也许您希望自定义 SwoopPanel 在 UI 中的呈现方式,而解决此问题的唯一方法是更改 ItemsControl 的控件模板。现在,您可以将 SwoopPanel 直接添加到控件模板中,并使用该属性将其标记为 ItemsHost,ItemsControl 将放置它创建的所有模板化项目。
您是否必须以一种方式或另一种方式进行?不是,其中一个比另一个更有优势吗?好吧,第二种方式可以让你更好地控制 UI,第一种方式更容易。真的,你自己选择吧。我个人从未以第二种方式做过,但我认为它可能在一些地方有用。
Say I have an ItemsControl. I want to use a custom panel that swoops items in and out as you scroll; its called a SwoopPanel. Now, how do I tell the ItemsControl to use my SwoopPanel to contain the templates it creates?
The quick way is to set the ItemsPanel on the ItemsControl:
However, sometimes that doesn't work for you. Maybe you wish to customize how the SwoopPanel is presented in the UI, and the only way to get around this is to change the control template of the ItemsControl. Now you can add your SwoopPanel directly to the control template and, using the property, mark it as the ItemsHost that the ItemsControl will put all the templated items it creates.
Do you have to do it one way or the other? No. Is one more advantageous than the other? Well, the second way allows you more control of the UI, the first way is easier. Take your pick, really. I've never personally done it the second way, but I think there might be a couple of places where it might be useful.
请更多解释!
虽然上述所有答案在技术上都是正确的,但我认为它们没有说明
IsItemsPanel
如何与ControlTemplate
以及ItemsPresenter 的存在(或不存在)相关联
及其使用的相应ItemsPanel
属性。这个答案将试图阐明这些事情,并希望澄清您何时应该或不应该使用它们。ItemsControls、Panels 和 IsItemsHost,天哪!
ItemsControl
只是一个显示项目集合的控件。它通过首先生成单独的容器*来直观地表示项目,然后将这些容器交给特定的面板来布局以在屏幕上显示。添加或删除项目时,ItemsControl
会根据需要在面板中添加或删除相应的容器。* 注意:如果某个项目已经是容器类型的实例(由 IsItemItsOwnContainer 覆盖
ItemsControl
) - 即添加一个ListBoxItem< /code> 实例到
ListBox
的Items
集合 - 该项目只是按原样直接传递到面板,充当其自己的容器。用于托管和布局容器的特定面板是
ItemControl
的控件模板中找到的第一个面板,其IsItemsHost
属性设置为“True”。有两种方法可以指定哪个面板:
通过将
ItemsPresenter
插入到ControlTemplate
中,作为ItemsPanel 指定的面板的占位符
属性。 (这是最常见的方式。)通过将
Panel
直接插入到ControlTemplate
中,并将其IsItemsHost
属性显式设置为正确
。但您使用哪个以及为什么?请继续阅读以找出答案!
ItemsPresenter - “随心所欲!”
在
ItemsControl
(例如ListBox
)的典型ControlTemplate
中,模板在其内部某处指定一个ItemsPresenter
。下面是显示其使用方式的简化摘录:如您所见,模板中间的
ScrollViewer
内部指定了一个ItemsPresenter
。然而,您看不到的是用于布置项目的实际面板。那么如果模板中没有定义面板,那么它从哪里来呢?这就是
ItemsPanel
属性的用武之地。顾名思义,该属性定义了将使用哪个面板来托管和布局项目。但它没有说明该面板出现在ControlTemplate
中的位置。这让我们回到了
ItemsPresenter
。简而言之,它是一个占位符,本质上是“当设置ItemsPanel
属性时,我将在此处插入该面板并将其IsItemsHost
设置为True 自动。”
IsItemsHost - “我的方式还是高速公路!”
但是,如果您不希望某人能够更改您的面板,因为您的控件依赖于某些自定义面板实现,并且其他任何内容都会破坏功能,该怎么办?在这种情况下,您不要在模板中使用
ItemsPresenter
。相反,您需要指定要使用的确切面板。这就是
IsItemsHost
属性发挥作用的地方。当在ControlTemplate
中的面板上设置时,它告诉ItemsControl
使用该特定面板来托管生成的容器,无论ItemsPanel
是什么设置为。ItemsPanel
属性基本上被忽略。直接在模板中指定面板的另一个好处是您可以命名它并像任何其他模板部分一样访问它。
这是与上面相同的示例,但它不是使用
ItemsPresenter
,而是硬编码SpecializedPanel
来布置项目。我们通过将其IsItemsHost
属性设置为True
来指示这是我们想要用来托管项目的面板,最后,我们给它一个名称,以便我们可以直接从代码访问它。在本例中,由于模板不使用
ItemsPresenter
而是直接包含一个其IsItemsHost
设置为True
的面板,因此没有用户无需完全替换整个ControlTemplate
即可更换该面板。 (如前所述,ItemsPanel
属性将被忽略。)将其全部带回家...
回顾一下,如果您是控件作者并希望为控件的使用者提供更换控件的灵活性用于布置项目的面板,然后使用
ItemsPresenter
为您的ItemsControl
定义模板。确保还在模板中设置ItemsPanel
属性以指定默认面板。但是,如果想要“锁定”控件使用的面板,则不要在
ControlTemplate
中使用ItemsPresenter
。相反,您可以在模板中指定要直接使用的特定面板,然后将其IsItemsHost
属性设置为True
。希望这能准确地澄清发生了什么。
More Explanation, Please!
While all of the above answers are technically correct, I feel they don't illustrate how
IsItemsPanel
correlates to theControlTemplate
and the presence (or absence) of anItemsPresenter
and the correspondingItemsPanel
property which it uses. This answer will attempt to shed light on those things and hopefully clarify when you should, or shouldn't use each.ItemsControls, Panels and IsItemsHost, Oh my!
An
ItemsControl
is simply a control that displays a collection of items. It does this by first generating individual containers* to represent the items visually, then it hands those containers over to a specific panel to be laid out for display on screen. As items are added or removed, theItemsControl
adds or removes the corresponding containers from the panel as needed.* Note: If an item is already an instance of the container type (as determined by the result of the IsItemItsOwnContainer override of the
ItemsControl
)--i.e. you add aListBoxItem
instance to theItems
collection of aListBox
--that item is simply passed through as-is directly to the panel, acting as its own container.The specific panel used for hosting and laying out the containers is the first one found in the
ItemControl
's control template that has itsIsItemsHost
property set to 'True'.There are two ways to specify which panel that is:
By inserting an
ItemsPresenter
into theControlTemplate
to act as a placeholder for the panel specified by theItemsPanel
property. (This is the most common way.)By inserting a
Panel
directly into theControlTemplate
and explicitly setting itsIsItemsHost
property toTrue
.But which do you use and why? Read on to find out!
ItemsPresenter - "Have It Your Way!"
In a typical
ControlTemplate
for anItemsControl
such as aListBox
, the template specifies anItemsPresenter
somewhere inside of it. Here's a simplified excerpt showing how it's used:As you can see, there is an
ItemsPresenter
specified inside of aScrollViewer
in the middle of the template. What you don't see however is an actual panel to lay out the items.So if there's no panel defined in the template, where does it come from? That's where the
ItemsPanel
property comes in. As its name suggests, this property defines which panel will be used to host and lay out the items. It doesn't however say where that panel appears in theControlTemplate
.That brings us back to the
ItemsPresenter
. In short, it's a placeholder that essentially says "When theItemsPanel
property is set, I'll insert that panel here and set itsIsItemsHost
toTrue
automatically."IsItemsHost - "My Way or the Highway!"
However, what if you don't want someone to be able to change out your panel because your control depends on some custom panel implementation and anything else will break the functionality? In that case, you don't use an
ItemsPresenter
in your template. You instead need to specify the exact panel you want to use.This is where
IsItemsHost
property comes into play. When set on a panel in theControlTemplate
, it tells thatItemsControl
to use that specific panel to host the generated containers, regardless of whatItemsPanel
is set to. TheItemsPanel
property is essentially ignored.Another benefit of specifying the panel directly in the template is you can then name it and access it just like any other template part.
Here's the same example as above, but rather than an
ItemsPresenter
, it hard-codes aSpecializedPanel
to lay out the items. We indicate that's the panel we want to use to host the items by setting itsIsItemsHost
property toTrue
and finally, we give it a name so we can access it directly from code.In this case, because the template doesn't use an
ItemsPresenter
and instead directly includes a panel with itsIsItemsHost
set toTrue
, there is no way for the user to change out that panel short of completely replacing the entireControlTemplate
. (As mentioned before, theItemsPanel
property is ignored.)Bringing it all home...
To recap, if you're a control author and want to give consumers of your control the flexibility to swap out the panel used to lay out your items, then define your template for your
ItemsControl
using anItemsPresenter
. Make sure to also set theItemsPanel
property in the template to specify a default panel.If however, want to 'lock' which panel your control uses, then do not use an
ItemsPresenter
in theControlTemplate
. Instead, specify the specific panel you want to use directly in the template, then set itsIsItemsHost
property toTrue
.Hope this clarifies exactly what's going on.
请参阅 http://msdn.microsoft。 com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.90).aspx
本质上,这篇文章所说的是,如果您要替换 ListBox 的 ControlTemplate 并想要一个新布局,在某些面板(例如 StackPanel)上设置 IsItemsHost=true。然后,ListBox 中的任何项目都将自动添加为 StackPanel 的子项。如果列表框的方向是水平的,则列表框将是水平的。
另一种方法是将 ListBox 的 ItemsPanel 属性设置为 ItemsTemplate,并且在该模板中您有一个 StackPanel。在这种情况下,ListBox 项目将被添加到 StackPanel 子级中,就像第一种情况一样。但是,您不需要设置 IsItemsHost = true,它绝对没有效果。这是通过您设置 ItemsPanel 属性来完成的。
See http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.isitemshost(v=vs.90).aspx
Essentially, what this post says is that if you are replacing the ControlTemplate of a ListBox and want a new layout, set IsItemsHost=true on some panel, e.g. a StackPanel. Then any items in the ListBox will be automatically added as children of the StackPanel. If the orientation of the ListBox is Horizontal, then the ListBox will be horizontal.
The other way is to set the ItemsPanel property of the ListBox to an ItemsTemplate and in that template you have a StackPanel. In this case the ListBox items will be added to the StackPanel children just as in the first case. However, you do not need to set IsItemsHost = true, it will have absolutely no effect. This is done for you by the fact that you are setting the ItemsPanel property.