Wpf 中的ListBoxItem样式(<;ListBox.Resources>;或在<;ListBox.ItemContainerStyle>;?

Wpf 中的ListBoxItem样式(<;ListBox.Resources>;或在<;ListBox.ItemContainerStyle>;?,wpf,xaml,listbox,styles,Wpf,Xaml,Listbox,Styles,我可以在或中为ListBoxItem添加xaml样式。请参阅代码。 问题是:有什么区别,我应该更喜欢什么 <ListBox.Resources> <Style TargetType="ListBoxItem"> <Setter Property="Canvas.Top" Value="{Binding Top}"/> <Setter Property="Canvas.Left" Value="{Binding Le

我可以在
中为
ListBoxItem
添加xaml
样式。请参阅代码。
问题是:有什么区别,我应该更喜欢什么

<ListBox.Resources>
    <Style TargetType="ListBoxItem">
        <Setter Property="Canvas.Top" Value="{Binding Top}"/>
        <Setter Property="Canvas.Left" Value="{Binding Left}"/>
        <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        <Setter Property="Padding" Value="0"/>
    </Style>
</ListBox.Resources>

或:


我接受一个答案,但请注意并思考这个奇怪的症状:
无论哪种方式都会给我一个奇怪的数据绑定警告:找不到引用为“RelativeSource FindAncestor,AncestorType='System.Windows.Controls.ItemsControl',AncestorLevel='1'的绑定源。BindingExpression:Path=HorizontalContentAlignment;DataItem=null。。。。等等
这是一个隐藏在系统Aero styles中某处的绑定,它不是我的。

只有当我同时使用两种样式时,此警告才会消失

第一个是
默认样式
,第二个是
显式样式

第一个将应用于父列表框的VisualTree下的所有
ListBoxItems

<ListBox>
  <ListBox.Resources>
    <!-- default Style -->
  </ListBox.Resources>
  <ListBox.ItemTemplate>
     <DataTemplate>
        <ListBox>
           <ListBoxItem/> <-- Will be applied to this as well.
        </ListBox>
     </DataTemplate>
  </ListBox.ItemTemplate>
</ListBox>

如果您查看通过ILSpy在
PresentationFramework.Aero.dll
下声明的默认样式,您可以在那里看到这两个设置器:

<Setter Property="HorizontalContentAlignment"
        Value="{Binding Path=HorizontalContentAlignment, 
         RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment"
            Value="{Binding Path=VerticalContentAlignment,
         RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>

ItemContainerStyle
是实现这一点的正确方法,因为它是显式设置的,所以wpf不需要总是查找样式可能所在的位置。它更快更好。这就是为什么有这样的财产


未设置
ItemContainerStyle
时,WPF将在
ListBox.Resources
窗口.Resources
应用程序.Resources
中查找样式。这对性能不利。

不同之处在于,如果您输入
资源
,它将应用于可视化树中的所有
ListBoxItem
子项。因此,如果您嵌套了
列表框
,它将应用于该列表框,并且与
ItemContainerStyle
相反,后者将仅应用于此
列表框
尝试将ItemContainerStyle列表框Item style中的OverridesDefaultStyle设置为true以删除绑定错误。该属性在中不可用
ItemContainerStyle
。我指的是ItemContainerStyle部分中的ListBoxItem样式o是的,我得到一个空的控件模板,所以我必须定义一个完整的ListBoxItem控件模板。这是断言的一部分-
更快更好
。任何支持该断言或数据的链接?请调试源代码,您将看到。一旦ItemContainerStyle设置,标志haslocalstyle将被设置为true,因此树遍历器将不会是用户访问逻辑树或可视树中的节点以查找默认或隐式样式。不确定msdn文档中是否提到了这一点。可能不会。请参阅问题中的“我的编辑”以了解后续症状。您的意思是-
将比
慢,因为第一个将遍历到根目录以查找样式?是的,但效果以毫秒为单位,如果您在编写自己的主题时有20个resourcedictionary,您会注意到listbox没有由于项目被添加或删除到visualtree中,因此滚动将不再平滑,每次更改时,查找过程都必须继续这20个ResourceDictionary。因此,从技术上来说,集装箱方式将是最好的方式。最后,这两种方法都会给你一种风格。但是,一个比另一个快。有关后续症状,请参阅问题中的“我的编辑”。绑定定义在哪里?你也可以发布它。补充:这是一个隐藏在某个系统样式中的系统绑定。它使用Wpf检查器显示。我自己的setter(见问题)试图摆脱它,只有当我在两个地方都这么做时才成功。@Gerard-在我的问题中添加了这些绑定错误的原因。@Gerard-可能是我不够清楚。我的意思是,如果您在ResourceOnly下声明它,并同时设置
HorizontalContentAlignment
VerticalContentAlignment
错误就会消失。但如果您将其设置为
ItemContainerStyle
,它不会消失,因为该样式仍然基于默认样式。您必须将
BasedOn
设置为
x:Null
才能避免该错误。
<Grid>
  <Grid.Resources>
     <Style x:Key="MyStyle" TargetType="ListBoxItem"/>
  </Grid.Resources>
  <ListBox ItemContainerStyle="{StaticResource MyStyle}"/>
</Grid>
<Setter Property="HorizontalContentAlignment"
        Value="{Binding Path=HorizontalContentAlignment, 
         RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment"
            Value="{Binding Path=VerticalContentAlignment,
         RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<ListBox>
   <ListBox.ItemContainerStyle>
      <Style TargetType="ListBoxItem" BasedOn="{x:Null}"/>
   </ListBox.ItemContainerStyle>
</ListBox>