WPF: как растянуть средний дочерний элемент в DockPanel?

Я добавил DockPanel к элементу RadioButton, чтобы я мог распределить метку переключателя, текстовое поле и кнопку по горизонтали, используя 100% ширины.

Использование LastChildFill="True" внутри DockPanel растягивает последний элемент. Это хорошо работает, если текстовое поле является последним дочерним элементом панели. Но поскольку кнопка является последним элементом и имеет фиксированную ширину, текстовое поле следует растянуть. Однако такого свойства, как 2ndChildFill="True", нет.

Мой код выглядит так:

    <RadioButton HorizontalAlignment="Stretch"
                                        HorizontalContentAlignment="Stretch">
        <DockPanel >
            <TextBlock VerticalAlignment="Center">in location:</TextBlock>
            <TextBox Grid.Column="1" Margin="10,0,0,0">Path string</TextBox>
            <Button HorizontalAlignment="Right" 
                    Margin="10,0,0,0" Padding="3,0">...</Button>
        </DockPanel>
    </RadioButton>

И это дает мне следующее:

скриншот wpf

Есть идеи, подсказки, как это исправить? Спасибо заранее...


person brgn    schedule 25.12.2012    source источник
comment
Почему бы вам вместо этого не использовать сетку? Сетка с 3 столбцами, для второго задана ширина *, а для остальных - авто.   -  person Charleh    schedule 26.12.2012
comment
Да, это могло сработать. Но мне это кажется немного изощренным. Не было бы DockPanel-Solution немного более элегантным? Ему не нужны все эти определения столбцов.   -  person brgn    schedule 26.12.2012


Ответы (2)


Вам необходимо установить прикрепленное свойство DockPanel.Dock для ваших элементов и оставьте TextBox в качестве последнего элемента:

<RadioButton HorizontalAlignment="Stretch"
             HorizontalContentAlignment="Stretch">
    <DockPanel LastChildFill="True">
        <TextBlock DockPanel.Dock="Left"
                   VerticalAlignment="Center"
                   Text="in location:" />
        <Button DockPanel.Dock="Right"
                Margin="10,0,0,0"
                Padding="3,0"
                Content="..." />
        <TextBox Margin="10,0,0,0">
            Path string
        </TextBox>
    </DockPanel>
</RadioButton>
person max    schedule 25.12.2012
comment
В заголовке вопроса упоминается «середина», а ответ перемещает его в «последний». Так почему нет лучшего ответа? - person Lei Yang; 08.01.2014
comment
Текстовое поле по-прежнему будет отображаться посередине из-за атрибутов DockPanel.Dock. Перемещение его в последнюю позицию в XML-документе просто заставляет WPF предоставить элементу управления все оставшееся пространство родительского элемента управления. - person Nick Pruehs; 16.09.2014
comment
Я пробовал это, но это портит мне порядок табуляции! Поскольку WPF назначает индекс вкладки по умолчанию в порядке в xaml, было бы предпочтительнее не перемещать элемент. - person aliceraunsbaek; 25.05.2016
comment
Чтобы уточнить, DockPanel имеет свойство LastChildFill, которое, когда установлено значение true, расширяет последний элемент, чтобы заполнить оставшуюся часть контейнера. Я думаю, что значение по умолчанию для этого - True (но вы можете установить его на истинную явность, если хотите). - person goldenratio; 14.11.2018

Принятый ответ решает вашу проблему, но создает новую. Если кто-то использует клавиатуру (TAB) для навигации по вашему интерфейсу, Button будет сфокусирован перед TextBox. В долгосрочной перспективе это может очень раздражать. Если вы не хотите нарушать порядок вкладок, используйте Grid вместо DockPanel:

<RadioButton HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" VerticalAlignment="Center">in location:</TextBlock>
        <TextBox Grid.Column="1" Margin="10,0,0,0">Path string</TextBox>
        <Button Grid.Column="2" HorizontalAlignment="Right" Margin="10,0,0,0" Padding="3,0">...</Button>
    </Grid>
</RadioButton>

Альтернативой может быть самостоятельное управление порядком табуляции с помощью атрибута TabIndex. Однако это может быть непросто, особенно когда вы отображаете свой элемент управления в коллекции.

<RadioButton HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch" TabIndex="0">
    <DockPanel LastChildFill="True">
        <TextBlock DockPanel.Dock="Left" VerticalAlignment="Center" Text="in location:" />
        <Button DockPanel.Dock="Right" Margin="10,0,0,0" Padding="3,0" Content="..." TabIndex="2"/>
        <TextBox Margin="10,0,0,0" TabIndex="1">Path string</TextBox>
    </DockPanel>
</RadioButton>
person Pawel    schedule 01.04.2021