I can put a xaml Style
for ListBoxItem
in <ListBox.Resources>
or in <ListBox.ItemContainerStyle>
. See code.
Question is: what is the difference, what should I prefer?
<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>
OR:
<ListBox.ItemContainerStyle>
<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.ItemContainerStyle>
There is an answer that I accept, but behold and think about this strange symptom:
Either way gives me this strange databinding warning: Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.ItemsControl', AncestorLevel='1''. BindingExpression:Path=HorizontalContentAlignment; DataItem=null .... etc.
This is a binding that is hidden somewhere in the system Aero styles, it is not mine.
Only when I use both styles this warning disappears!
ItemContainerStyle
is the right way to do this because its set explicitly and so wpf will not need to look up always where the style might be. Its faster and better. That is why that property is there.
When ItemContainerStyle
is not set WPF will seek for the style in ListBox.Resources
or Window.Resources
or Application.Resources
. That is bad for performance.
First is default Style
and second is Explicit style
.
First one will be applied to all ListBoxItems
found under VisualTree of parent ListBox.
<ListBox>
<ListBox.Resources>
<!-- default Style -->
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox>
<ListBoxItem/> <-- Will be applied to this as well.
</ListBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
whereas second one will be applied to only ListBoxItems
corresponding to outer ListBox.
Second is equivalent to:
<Grid>
<Grid.Resources>
<Style x:Key="MyStyle" TargetType="ListBoxItem"/>
</Grid.Resources>
<ListBox ItemContainerStyle="{StaticResource MyStyle}"/>
</Grid>
If you look at the default style declared under PresentationFramework.Aero.dll
via ILSpy, you can see these two setters over there:
<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}}}"/>
So, when you set that in your default style declared under resource, it overrides those setters and hence error goes away.
But, in case you set it on style declared inline of ItemContainerStyle
that error won't go away since it still refer to the default style. In case you don't want to basedOn default style set BasedOn
attribute to x:Null
.
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem" BasedOn="{x:Null}"/>
</ListBox.ItemContainerStyle>
</ListBox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With