代码之家  ›  专栏  ›  技术社区  ›  Armentage

panel.isitemshost究竟做了什么?

  •  32
  • Armentage  · 技术社区  · 14 年前

    我找不到任何关于panel.istitemshost附加属性的良好文档。我看到很多人在itemscontainer模板上为itemscontrol设置它的例子,但是联合国在msdn上的文档并不能解释设置属性的原因或优点。我已经建造了很多容器,它们没有设置这个属性,但是还没有注意到任何不良影响。

    3 回复  |  直到 5 年前
        1
  •  36
  •   Will    14 年前

    假设我有一个项目控制。我想使用一个定制的面板,当你滚动的时候,它可以将物品快速地输入和输出,这叫做swooppanel。现在,如何告诉itemscontrol使用我的swooppanel来包含它创建的模板?

    快速方法是在itemscontrol上设置itemspanel:

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

    然而,有时候这对你来说并不管用。也许您希望自定义Swooppanel在用户界面中的显示方式,而解决此问题的唯一方法是更改itemsControl的控制模板。现在,您可以直接将您的swooppanel添加到控件模板中,并使用属性将其标记为项控件将放置其创建的所有模板化项的项列表。

    <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>
    

    你必须这样做还是那样做?不,一个比另一个更有利吗?好吧,第二种方法允许您对UI进行更多的控制,第一种方法更简单。真的,你自己挑吧。我从来没有亲自做过第二种方式,但我认为可能会有一些地方它可能是有用的。

        2
  •  12
  •   Richard    10 年前

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

    本质上,本文所说的是,如果您要替换列表框的ControlTemplate并需要新的布局,请在某些面板(例如StackPanel)上设置isitemshost=true。然后,列表框中的任何项都将自动作为stackpanel的子项添加。如果列表框的方向是水平的,则列表框将是水平的。

    另一种方法是将列表框的itemspanel属性设置为itemstemplate,在该模板中有stackpanel。在这种情况下,列表框项将添加到stackpanel子项,就像在第一种情况下一样。但是,您不需要设置isitemshost=true,它绝对没有任何效果。这是通过设置itemspanel属性来实现的。

        3
  •  0
  •   Mark A. Donohoe    5 年前

    请提供更多详细信息!

    虽然以上所有答案在技术上都是正确的,但它们实际上缺少解释 IsItemsPanel ControlTemplate 以及 ItemsPresenter 元素与 ItemsPanel 财产。

    按你的方式去做!

    在一个典型 控件模板 对于一个 ItemsControl 比如A ListBox ,模板定义一个名为 项目经理 . 以下是 列表框 模板:

    <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>
    

    正如你所看到的,有一个 项目经理 在模板中间指定。但是,你看不到的是一个实际布局项目的面板。

    所以,如果模板中没有定义面板,那么它来自哪里?这就是 iTimeSpell 财产进来了。顾名思义,这个属性定义了哪个面板将用于托管和布局项目。但是,它没有说明该面板在模板中的显示位置。让我们回到 项目经理 . 它本质上是 控件模板 上面写着“当你设置 iTimeSpell ,我把它放在这里,然后把它 IsItemsHost 为了你!”

    使用 项目经理 在你 项目控制 模板是您正在使控件的使用者很容易替换 iTimeSpell 无需完全重新设置整个控件的模板。

    我的路还是高速公路!

    但是,如果您不希望有人能够更改您的面板,因为它需要一些自定义实现,而其他任何东西都会破坏该功能,该怎么办?在这种情况下,你 不要 使用一个 项目经理 在模板中。而是直接定义面板。这里就是 iSimeStuST 开始发挥作用。

    这里有与上面相同的例子,但不是 项目经理 ,IT硬代码A SpecializedPanel 布置项目。我们通过设置 iSimeStuST 属性。

    <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>
    

    在这种情况下,因为没有 项目经理 而模板直接定义了它要用于项目的面板,除了完全替换整个面板之外,用户无法更改该面板。 控件模板 .

    综上所述…

    概括地说,如果您是控件作者,并且希望让用户能够交换用于布局项目的面板,请为您的 项目控制 使用一个 项目经理 (不要忘记定义通过 ItemsTemplate 属性)

    如果要“锁定”控件使用的面板,请不要使用 项目经理 在模板中。相反,直接指定要用于承载项的面板并设置其 iSimeStuST 属性设置为“true”

    注意:从技术上讲,还有第三种情况,这可以说是更常见的:您不是控件的作者,而是简单地重新模板化类似 列表框 供您在特定页面/屏幕上使用。在这种情况下,由于您不必担心下游的其他用户,因此可以使用 iSimeStuST 不用担心 iTimeSpell / 项目经理 组合或其增加的复杂性。

    这是因为您的本地更改不会影响控件的任何其他使用,因为您没有更改默认值 控件模板 . 您只是为自己的特定实例更改它。

    说,你 可以 仍然使用 iTimeSpell / 项目经理 组合和纯粹主义者会争辩说这是正确的方式,但是除非你真的需要下游的其他人灵活地交换面板以满足他们的需要(即,你在模板化 列表框 在你的应用程序的根,做一些花哨的布局,但在应用程序的其他地方的消费者可能仍然需要换掉他们的特定屏幕的面板),它只是增加更多的工作为自己。

    希望这能清楚地说明到底发生了什么。