Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListBoxItem style in <ListBox.Resources> or in <ListBox.ItemContainerStyle>?

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!

like image 907
Gerard Avatar asked Feb 15 '14 15:02

Gerard


2 Answers

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.

like image 124
dev hedgehog Avatar answered Sep 28 '22 05:09

dev hedgehog


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>
like image 44
Rohit Vats Avatar answered Sep 28 '22 04:09

Rohit Vats