Tuesday, February 8, 2011

How do I make a WPF data template fill the entire width of the listbox?

I have a listbox data template in WPF. I want one item to be tight against the left side of the listbox and another item to be tight against the right side, but I can't figure out how to do this.

So far I have a grid with three columns, the left and right ones have content and the center is a placeholder with it's width set to "*". Where am I going wrong?

EDIT: Here is the code:

<DataTemplate x:Key="SmallCustomerListItem">
    <Grid HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <WrapPanel HorizontalAlignment="Stretch" Margin="0">
            <!--Some content here-->
            <TextBlock Text="{Binding Path=LastName}" TextWrapping="Wrap" FontSize="24"/>
            <TextBlock Text=", " TextWrapping="Wrap" FontSize="24"/>
            <TextBlock Text="{Binding Path=FirstName}" TextWrapping="Wrap" FontSize="24"/>

        </WrapPanel>
        <ListBox ItemsSource="{Binding Path=PhoneNumbers}" Grid.Column="2" d:DesignWidth="100" d:DesignHeight="50"
     Margin="8,0" Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False" HorizontalAlignment="Stretch"/>
    </Grid>
</DataTemplate>
  • The Grid should by default take up the whole width of the ListBox because the default ItemsPanel for it is a VirtualizingStackPanel. I'm assuming that you have not changed ListBox.ItemsPanel.

    Perhaps if you got rid of the middle ColumnDefinition (the others are default "*"), and put HorizontalAlignment="Left" on your WrapPanel and HorizontalAlignment="Right" on the ListBox for phone numbers. You may have to alter that ListBox a bit to get the phone numbers even more right-aligned, such as creating a DataTemplate for them.

  • Ok, here's what you have:

    Column 0: WrapPanel
    Column 1: Nothing
    Column 2: ListBox

    It sounds like you want WrapPanel on the left edge, ListBox on the right edge, and space to take up what's left in the middle.

    Easiest way to do this is actually to use a DockPanel, not a Grid.

    <DockPanel>
        <WrapPanel DockPanel.Dock="Left"></WrapPanel>
        <ListBox DockPanel.Dock="Right"></ListBox>
    </DockPanel>
    

    This should leave empty space between the WrapPanel and ListBox.

    From 17 of 26
  • If you want to use a Grid then you need to change your ColumnDefinitions to be:

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions
    

    If you don't need to use a Grid, then you could use a DockPanel:

        <DockPanel>
            <WrapPanel DockPanel.Dock="Left">
                <!--Some content here-->
                <TextBlock Text="{Binding Path=LastName}" TextWrapping="Wrap" FontSize="24"/>
                <TextBlock Text=", " TextWrapping="Wrap" FontSize="24"/>
                <TextBlock Text="{Binding Path=FirstName}" TextWrapping="Wrap" FontSize="24"/>
            </WrapPanel>
            <ListBox DockPanel.Dock="Right" ItemsSource="{Binding Path=PhoneNumbers}" 
     Margin="8,0" Background="Transparent" BorderBrush="Transparent" IsHitTestVisible="False"/>
            <TextBlock />
        </DockPanel>
    

    Notice the TextBlock at the end... any control with no "DockPanel.Dock" defined will fill the remaining space.

    Kevin Berridge : This does NOT make the datatemplate fill the width of the listbox.
    From Phobis
  • I also had to set

    HorizontalContentAlignment="Stretch"
    

    on the containing listbox.

    Binary Worrier : Ta pal. Googled for help and this was on the first link. Nice one :)
    Tim : If I could vote this up more than once I would!

0 comments:

Post a Comment