WPF:我如何在DockPanel中拉伸中间的子元素?

46

我将一个DockPanel添加到一个RadioButton元素中,以便我可以使用100%的宽度水平分配单选按钮标签、文本框和按钮。

在DockPanel中使用LastChildFill="True"会拉伸最后一个元素。如果文本框是面板中的最后一个子元素,则效果很好。但是,由于按钮是最后一个元素且具有固定宽度,因此应拉伸文本框。然而,没有像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截图

有什么想法或提示可以解决这个问题吗?非常感谢提前...


2
为什么不使用网格布局呢?使用三列的网格布局,其中第二列设置为*宽度,其他列设置为自动。 - Charleh
1
是的,那可能行得通。但是对我来说看起来有点过度设计了。DockPanel-Solution不是更加优雅一些吗?它不需要所有这些列定义。 - brgn
2个回答

71

您需要为您的元素设置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>

4
问题的标题提到了“中间”,但回答却将其移动到了“最后”。那么为什么没有更好的答案呢? 为什么没有更好的答案,我不清楚。但是回答者可能认为将事物放在某些情况下的顺序可能会更清晰或有逻辑性。 - Lei Yang
12
由于DockPanel.Dock属性的存在,文本框仍将呈现在中间。将其移至XML文档中的最后位置只是使WPF授予该控件父控件的所有剩余空间。 - Nick Pruehs
2
我尝试过这个,但它会破坏我的选项卡顺序!由于WPF按照xaml中的顺序分配默认选项卡索引,最好不要移动元素。 - aliceraunsbaek
2
澄清一下,DockPanel 有一个属性 LastChildFill,当设置为 true 时,将扩展最后一个元素以填充容器的剩余部分。我认为默认值为 True(但如果需要,您也可以显式地将其设置为 true)。 - goldenratio

5

接受的答案可以解决您的问题,但会产生另一个问题。 如果有人使用键盘(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>

2
我同意,这是一个更好的方法。另一个答案并没有错,但是这里的布局更加直观,因为控件按照它们在用户界面上出现的顺序列出。谢谢。 - Sabuncu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接