views:

8109

answers:

3

I have a ListBox with it's ItemTemplate bound to a DataTemplate. My problem is I cannot get the elements in the template to stretch to the full width of the ListBox.

<ListBox x:Name="listPeople" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
    Margin="0,0,0,0" Background="{x:Null}" SelectionMode="Extended" Grid.Row="1" 
    ItemTemplate="{StaticResource PersonViewModel.BrowserDataTemplate}" 
    ItemsSource="{Binding Mode=OneWay, Path=SearchResults}" >
</ListBox>

<DataTemplate x:Key="PersonViewModel.BrowserDataTemplate">
   <ListBoxItem HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
     <Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="5,5,5,5">
       <Border Opacity=".1" x:Name="itemBorder"  Background="#FF000000"   
         HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
         CornerRadius="5,5,5,5" MinWidth="100" Height="50"/>
      </Grid>
   </ListBoxItem>
</DataTemplate>

As you can see, I have added a border within the grid to indicate the width of the template. My goal is to see this border expand to the full width of the listbox. Currently its width is determined by its contents or MinWidth, which is the only thing at the moment keeping it visible at all.

A: 

Two things I noticed here, because I had the same issue and wasn't able to solve it the way you're trying.

First, you don't need to explicitly put a ListBoxItem in your DataTemplate. This is created for you automatically, so you actually have your ListBoxItem inside of the one that was created for you. I checked this out in Snoop to confirm.

Second, and I don't know exactly why, but I wasn't able to get the stretching behavior out of the alignment attributes either. I changed it to use RelativeSource binding on the Width attribute to the ActualWidth property of the containing ListBoxItem. This worked for me.

Width="{Binding RelativeSource={RelativeSource 
   AncestorType={x:Type ListBoxItem}}, Path=ActualWidth}"

If you need to set style properties on the ListBoxItem that is implicitly created for you, use a Style element inside of the ListBox.ItemContainerStyle element.

Hope this helps...

Rich
I do not believe RelativeSource is available in Silverlight.
Lee
You're right...I wasn't thinking about that. You can do Element-to-Element binding in SL3 though, so just bind Width of the Grid to ActualWidth of the ListBox, etc. If it's a bit off because of padding or anything like that, you can use an IValueConverter to fix it up.
Rich
Do you have more sample code for this. I am using WPF and I have a ListBox setup with the DataTemplate configured with a Grid. I also have the ListBox.ItemContainerStyle setup with a Template and HorizontalContentAlignment set to Stretch however this doesn't fix the issue. I was hoping I could place the RelativeBinding to the ActualWidth like you have in your sample code above.
Luke
I tried setting the width in the ListBox.ItemContainerStyle using <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=ActualWidth}"/> and that didn't work.
Luke
+11  A: 

When creating Data Templates for ListBox, you should not incldue . The contents of the DataTemplate will be placed inside of a generated container. You can control how that container is constructed using ItemContainerStyle.

The default control style for ListBoxItem is used to define the ItemContainerStyle by default. This style sets the ListBoxItem.HorizontalContentAlignment property to 'Left'. Notice how the ContentPresenter binds its HorizontalAlignment to this property.

You need to override the style of the ListBoxItem container that is being generated when you bind to your ListBox. This can be done by setting the ItemContainerStyle. Set the HorizontalContentAlignment property to be "Stretch".

Below is the default ListBoxItem Style. Included for reference.

<Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
      <Setter Property="Padding" Value="3"/>
      <Setter Property="HorizontalContentAlignment" Value="Left"/>
      <Setter Property="VerticalContentAlignment" Value="Top"/>
      <Setter Property="Background" Value="Transparent"/>
      <Setter Property="BorderThickness" Value="1"/>
      <Setter Property="TabNavigation" Value="Local"/>
      <Setter Property="Template">
       <Setter.Value>
        <ControlTemplate TargetType="ListBoxItem">
         <Grid Background="{TemplateBinding Background}">
          <!-- VSM excluded for readability -->
          <Rectangle x:Name="fillColor" Fill="#FFBADDE9" RadiusX="1" RadiusY="1" IsHitTestVisible="False" Opacity="0"/>
          <Rectangle x:Name="fillColor2" Fill="#FFBADDE9" RadiusX="1" RadiusY="1" IsHitTestVisible="False" Opacity="0"/>
          <ContentPresenter x:Name="contentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
          <Rectangle x:Name="FocusVisualElement" Stroke="#FF6DBDD1" StrokeThickness="1" RadiusX="1" RadiusY="1" Visibility="Collapsed"/>
         </Grid>
        </ControlTemplate>
       </Setter.Value>
      </Setter>
     </Style>
markti
Thanks! That's exactly what I needed!
Lee
Excellent, thanks so much.
Jeff Wilcox
Great job, thanks!
esylvestre
+6  A: 

I spent an hour trying to resolve this one. Very very frustrasting. You don't have to override the entire default style for the ListBoxItem. I couldn't get this to work. In the end I resolved the issue by simply overriding just the HorizontalContentAlignment property in my ListBox.ItemContainerStyle section e.g:

            <ListBox x:Name="ClassList" ItemsSource="{Binding LineClasses}"
                     ScrollViewer.VerticalScrollBarVisibility="Visible"
                     SelectionMode="Extended"
                     ScrollViewer.HorizontalScrollBarVisibility="Hidden" HorizontalContentAlignment="Stretch"
                     HorizontalAlignment="Stretch" Loaded="ClassList_Loaded"
                     VerticalAlignment="Stretch" Grid.Row="0">
                <ListBox.ItemContainerStyle>
                    <Style TargetType="ListBoxItem">
                        <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
                    </Style>
                </ListBox.ItemContainerStyle>
                    <ListBox.ItemTemplate>

                    <DataTemplate>
                        <Border BorderBrush="Black" CornerRadius="3" Background="#FFE88D34"
                            BorderThickness="1" HorizontalAlignment="Stretch" >
                            <Grid Background="Transparent" HorizontalAlignment="Stretch" >
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>
                                <TextBlock 
                                    Grid.Column="0" HorizontalAlignment="Stretch"
                                    Margin="2"                                   
                                    FontSize="10"
                                    Text="{Binding DisplayClassNm}"/>
                            </Grid>

                        </Border>
                    </DataTemplate>
                </ListBox.ItemTemplate>

This worked a treat for me.

Myles

Myles J
The lines :<ListBox.ItemContainerStyle> ...</ListBox.ItemContainerStyle>Have worked for me, clean and simple...
Gabriel Mongeon