如何使WPF的StackPanel从底部向上垂直填充?

41

我需要能够填充一个 stackpanel,其中包含一些 buttons,但这些按钮 必须先出现在 stackpanel 的底部,然后向上填充。这些按钮是动态创建的,数量不确定,因此视觉 hackery 就行不通。我已经尝试过垂直对齐,但没有成功。

7个回答

58

像这样:

<StackPanel VerticalAlignment="Bottom">
    ...
</StackPanel>

如果要向上填充按钮,您必须将按钮插入到位置0,而不是添加它们。


5
仅通过插入来填充当然只适用于在代码中手动添加元素。我在这里开发了(并得到了一些帮助)一个可逆的ReversibleStackPanel,可能对大家有所帮助:https://dev59.com/F0_Ta4cB1Zd3GeqPCJzm - devios1
2
遇到了类似的问题:通过设置 HorizontalAlignment="Right" 可以从右到左填充。 - ChriPf

17

或者你可以将StackPanel旋转180度,使按钮从底部到顶部堆叠,然后将按钮再旋转180度使它们正立:

<StackPanel>
    <!-- rotate all buttons inside this panel -->
    <StackPanel.Resources>
        <Style TargetType="Button">
            <Setter Property="LayoutTransform">
                <Setter.Value>
                    <RotateTransform Angle="180"/>
                </Setter.Value>
            </Setter>
        </Style>
    </StackPanel.Resources>

    <!-- rotate the stack panel -->
    <StackPanel.LayoutTransform>
       <RotateTransform Angle="180"/>
    </StackPanel.LayoutTransform>

    <!-- content -->
    <Button>1</Button>
    <Button>2</Button>

</StackPanel>

2
@chaiguy - 我认为你对这个问题的计算量负载看法是错误的,因为:1.变换非常高效,2.它们只在重新计算布局时运行-如果这对性能(或 CPU 使用率)有任何明显的影响,我会感到非常惊讶。 - Nir
在这种情况下,我可能是错的,但我记得看过一篇微软发布的关于提高WPF性能的文章,其中一个要点是避免过度使用LayoutTransforms - 主要是因为它们会导致额外的布局传递,但正如你所说,只有在更改时才会发生,所以可能并不是很重要。 - devios1
1
@chaiguy - 你是对的,LayoutTransform确实会引起布局传递 - 但只有在它发生变化时才会引起。他们所写的性能问题是动画布局转换(每秒30次布局传递显然非常消耗CPU)。在这个特定的例子中,变换永远不会引起额外的布局传递,因为它从未改变过。 - Nir

10

另一种选择是使用DockPanel。

在DockPanel上将LastChildFill设置为false即可。

然后在将按钮添加到Bottom之前,将附加的Dock属性设置为DockPanel上的每个按钮。

示例:

            var button = new Button();
            DockPanel.SetDock(button, Dock.Bottom);

3
"LastChildFill!真希望我之前知道这个!为什么他们不直接搞一个Dock.Fill呢,我永远都不会明白。整个把最后一个子元素当作填充的方式太荒谬了。" - devios1

4
用于解决这个问题的最佳方法是实现从StackPanel派生的自定义容器,但如果在运行时添加元素,则可以采用快速而简单的解决方案。
    public Window1()
    {
        InitializeComponent();
        for (int i = 0; i < 10; i++)
        {
            Button btn = new Button();
            btn.Content = "Button " + i;
            MyStack.Children.Insert(0, btn);
        }
    }

将项目插入到0位置,而不是添加它们。


我们需要至少一个可以接受的理由来更喜欢“代码”而不是XAML。 - Nuri YILMAZ

2

尝试将StackPanel放置在另一个容器中(不是StackPanel;可以是DockPanel),并将其底部对齐。然后当您填充按钮时,将每个新按钮放入第一个位置。


1

我发现使用Column=1的UniformGrid可以使堆栈整齐填充,或者Rows=1可以使水平方向上的堆栈整齐填充。而从索引0开始添加将从下往上工作。


1
使用UniformGrid的一个注意事项是,添加的每个元素都将具有相同的水平/垂直大小,因此,如果元素本身具有不同的大小,则它们在堆叠时不会像StackPanel一样接触。 - devios1

0

我喜欢Nir的变换解决方案。我在想是否可以使用变换来实现。

不过有一个注意点,不要在基于ScrollView的控件(例如ListBox)上使用变换技巧,因为滚动条操作会与内容反转。这看起来很有趣,只要你不是最终用户就好。


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