37

In a window I have there is a list of DockPanels to specify a couple of files. Each DockPanel has a TextBox (for the path) and a button (to browse for a file).

I've recreated a simple WPF page to demostrate the problem here:

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="150"
    Height="22">
    <DockPanel>
        <TextBox HorizontalAlignment="Stretch"/> <!-- path to file -->
        <Button Content="..." DockPanel.Dock="Right"/> <!-- button to browse for file -->
    </DockPanel>
</Page>

The problem is that I want the button to the right of the textbox, but that causes the textbox to be really small since the LastChild of the DockPanel is the button it uses up the remaining space. Ive tried to change this by shuffling them around and setting LastChildFill="False" but that only causes the button to be small again, not making the TextBox wide (even with HorizontalAlignment="Stretch").

The reason I want the controls in that order is I want the user to reach the TextBox before the Button when using tab to navigate in the window. I looked into setting TabIndex but it feels hacky, favorite features of WPF is that tabindex are in the order the conrols are defined in the XAML. Not to mention that I probably would have to manually set TabIndex on everything in the Window.

To me, it seems that the setting of TextBox.HorizontalAlignment isn't respected. How can I make the first control use as much space as it can but still preserve tab order?

Nate
  • 30,286
  • 23
  • 113
  • 184
Mizipzor
  • 51,151
  • 22
  • 97
  • 138

2 Answers2

55

Make it like this:

<DockPanel LastChildFill="True">
    <Button Content="..." DockPanel.Dock="Right"/> <!-- button to browse for file -->
    <TextBox DockPanel.Dock="Left" HorizontalAlignment="Stretch"/> <!-- path to file -->
</DockPanel>
Jonathan Barez
  • 559
  • 3
  • 2
  • 10
    Brilliant! Completely unintuitive and obnoxious, but worked like a charm and makes a weird kind of sense given how DockPanel is designed. Good call. – TonganJedi May 14 '11 at 01:40
  • 17
    I've seen this on several occasions. My main concern is that the order of the elements in the XAML no longer matches the visual layout of the window. And it messes up the tab order. – Christoffer Lette Oct 20 '11 at 08:37
  • 2
    I agree with @ChristofferLette +1, but just in case anybody needed it, here is the workaround for taborder problem. It can be quite a lot of manual work and doesn't always work well (for example with DataGrid): http://stackoverflow.com/a/4808810/724944 – surfen Mar 28 '12 at 00:35
  • Nice! I was fighting a similar issue and failed to realize that the child order didn't reflect the visual order, and this fixed my problem for me. – Nathan Dace Dec 06 '13 at 14:58
  • Did this in a basic context (one stretched top area and one bottom area) and the tab order was just fine. Perhaps the problem only shows up in certain conditions? – Chris Mar 07 '16 at 18:13
32

If you don't want the behavior of DockPanel, don't use a DockPanel.

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

    <TextBox />
    <Button Content="..." Grid.Column="1"/>
</Grid>
John Bowen
  • 24,213
  • 4
  • 58
  • 56
  • 5
    +1 because it doesn't have TabOrder issue. If anybody wants to avoid typing ColumnDefinitions in such simple scenarios, have a look at this solution: http://rachel53461.wordpress.com/2011/09/17/wpf-grids-rowcolumn-count-properties/ – surfen Mar 28 '12 at 00:44