24

I'm trying the content of a shopping cart in an ItemsControl(ListBox). To do so, I've created the following DataTemplate:

<DataTemplate x:Key="Templates.ShoppingCartProduct"
              DataType="{x:Type viewModel:ProductViewModel}">
    <DockPanel HorizontalAlignment="Stretch">
        <TextBlock DockPanel.Dock="Left"
                   Text="{Binding Path=Name}"
                   FontSize="10"
                   Foreground="Black" />
        <TextBlock DockPanel.Dock="Right"
                   Text="{Binding Path=Price, StringFormat=\{0:C\}}"
                   FontSize="10"
                   Foreground="Black" />
    </DockPanel>
</DataTemplate>

When the items are displayed in my shopping cart however, the Name and Price TextBlocks are sitting right beside one another, and there is an extremely large amount of whitespace on the right hand side.

Was wondering what the best method to force the DockPanel to stretch to fill all the space made available by the ListItem was?

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Richard McGuire
  • 10,780
  • 8
  • 31
  • 34

3 Answers3

34

Bind the Width of the DockPanel to the ActualWidth of the ListBoxItem:

<DockPanel Width="{Binding ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}}">
...

Another option: you could just redefine the ItemContainerStyle so that the ListBoxItem is stretched horizontally:

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    </Style>
</ListBox.ItemContainerStyle>
Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • I tried using that binding and it seems to be causing the ListBoxItem to continually grow in size, when viewing with Snoop, I saw the width of both the ListBoxItem and the DockPanel exceed 300,000. – Richard McGuire Jul 03 '09 at 19:23
  • 3
    Oh, ok, I get it... you must set LastChildFill="False" on the DockPanel, otherwise the second TextBlock is stretched – Thomas Levesque Jul 03 '09 at 20:47
  • I ended up locating your second approach and going that route. – Richard McGuire Jul 03 '09 at 21:13
  • the 2nd approach works if you use HorizontalContentAlignment instead of HorizontalAlignment. I edited the answer. – slfan Apr 25 '12 at 07:41
  • The first approach does not work if your ListBox is resized down. The actual size stays at its maximal value. – Benlitz Aug 20 '13 at 10:31
  • That's why I hate (sometimes) WPF. The simplest things are overcomplicated sooo much. Do you really need 5 lines of code to do.. `Dock="Fill"` thing ? – Ish Thomas Mar 21 '17 at 15:10
  • @IshThomas, this is only because the default style for `ListBoxItem` aligns it to the left, rather than stretch it. So it's not really WPF which is at fault here, just this specific control ;) – Thomas Levesque Mar 21 '17 at 17:49
  • I know, I was too general in my complains :) But that doesn't change the fact that sometimes while creating UI in WPF you think.."but.. why?" :) Many controls should be updated/upgraded so they can be used quickly – Ish Thomas Mar 21 '17 at 17:56
10

The nice thing about dock panels is they already fill all the available space. LastChildFill is true by default (but I set it below for clarity), so just don't set the DockPanel attribute on the last child, and it will fill the available space.

<DockPanel HorizontalAlignment="Stretch" LastChildFill="true">
    <TextBlock DockPanel.Dock="Left"
               Text="{Binding Path=Name}"
               FontSize="10"
               Foreground="Black" />
    <TextBlock 
               Text="{Binding Path=Price, StringFormat=\{0:C\}}"
               FontSize="10"
               Foreground="Black" />
</DockPanel>
NielW
  • 3,626
  • 1
  • 30
  • 38
9

DockPanels are evil. Temptation to use StackPanel/DockPanel combination for complex layouts leads to "layout dead ends". Use a Grid:

<Grid>
  <TextBlock HorizontalAlignment="Left"
...
  <TextBlock HorizontalAlignment="Right"
...
/Grid>

I use Grids almost exclusively, using a separate grid for each block of elements that "belong together"

Dave Clemmer
  • 3,741
  • 12
  • 49
  • 72
Sergey Aldoukhov
  • 22,316
  • 18
  • 72
  • 99
  • I don't think DockPanels are evil, they can be pretty useful sometimes... however I must agree that it was probably not the best option in that case – Thomas Levesque Jul 03 '09 at 21:18
  • Of course this is subjective and they are not an _absolute_ evil ;) But look where Rich already going - using ItemContainerStyle (semi-advanced stuff) for simple task - kinda indicative... – Sergey Aldoukhov Jul 03 '09 at 21:46
  • I had considered a Grid at the outset. However, given a narrow ListBox, or long enough value for the Name or Price properties the two TextBlocks will end up overlapping their values. In addition I would hardly classify laying out two TextBlocks at opposite ends of a panel as a "complex layout". – Richard McGuire Jul 08 '09 at 02:31
  • Sorry for commenting to this old post, but using a grid is also a simple and equally effective solution to the problem. The overlap problem is avoidable. +1 – code4life Jul 22 '11 at 12:51
  • This is an old answer, but I thought I'd point out that the problem with using a grid or panel in a ListBox's item template is that it's not one single element; it is a new element for each ListBoxItem and won't share the width of an other item unless explicitly set in the template. This makes setting the ItemContainerStyle content alignment to stretch a necessity when using a dynamic width. – Tim Jan 02 '19 at 17:19
  • Dock panels are a temptation because newcomers expect them to work like Windows Forms dock panels did, or even the QT and MFC versions for that matter. I find them far more cumbersome, requiring far more extra work to get the same results. Grid is usually what you want because they are flexible. The WPF seems highly customizable, like QT Quick but seems to miss the idea of the separation between code and presentation/design that was so important to them when WPF and XAML were first invented (remember when there was NO intellisense?). – osirisgothra Jun 22 '23 at 23:03