【问题标题】:How can a WPF StackPanel fill vertically from bottom to top?WPF StackPanel 如何从下到上垂直填充?
【发布时间】:2010-10-04 05:56:48
【问题描述】:

我需要能够用buttons 填充stackpanel,但按钮必须首先出现在堆栈面板的底部并向上填充。这些按钮是动态创建的,并且数量未知,因此视觉黑客无法正常工作。我尝试过垂直对齐,但无济于事。

【问题讨论】:

    标签: wpf stackpanel


    【解决方案1】:

    解决问题的最佳方法是实现从 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。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      像这样:

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

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

      【讨论】:

      • 当然,只有在代码中手动添加元素时,才能通过插入填充。我在这里(在一些帮助下)开发了一个可能对人们有用的 ReversibleStackPanel:stackoverflow.com/questions/3428622/…
      • 有一个类似的问题:通过设置HorizontalAlignment="Right"从右到左填充。
      【解决方案4】:

      另一种选择是使用 DockPanel。

      只需在 DockPanel 上将 LastChildFill 设置为 false。

      然后在添加到 DockPanel 之前,将附加的 Dock 属性设置到要添加到底部的每个按钮。

      例子:

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

      【讨论】:

      • LastChildFill!我希望我以前知道这一点!为什么他们不只是有一个 Dock.Fill 我永远不会知道。以最后一个孩子为填充的整个过程是荒谬的。
      【解决方案5】:

      我发现使用 Column=1 的 UniformGrid 可以提供整齐的填充堆栈,或者设置 Rows=1 可以提供整齐的水平填充堆栈。从索引 0 开始添加将自下而上进行。

      【讨论】:

      • 使用UniformGrid 的一个注意事项是添加的每个元素都将具有相同的水平/垂直尺寸,因此如果元素本身的尺寸不同,它们不会像@987654322 那样堆叠在一起@.
      【解决方案6】:

      或者您可以将 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>
      

      【讨论】:

      • @chaiguy - 我认为你对 CPU 密集型的看法是错误的,因为:1. 转换非常高效,2. 它们仅在重新计算布局时运行 - 如果这有任何明显的影响,我会感到非常惊讶对性能(或 CPU 使用)的影响
      • 在这种情况下我很可能是错的,但我确实记得看过一篇 MS 发表的关于提高 WPF 性能的文章,其中一个要点是避免过度使用 LayoutTransforms——主要是因为它们会导致额外的布局传递,但正如你所说,只有当它发生变化时才会发生,所以这可能没什么大不了的。
      • @chaiguy - 你是对的,LayoutTransform 确实会导致布局传递 - 但只有当它发生变化时 - 他们写的性能问题是动画布局转换(每秒 30 次布局传递显然非常CPU密集型)。在这个特定的例子中,转换永远不会导致额外的布局传递,因为它永远不会改变。
      【解决方案7】:

      喜欢 Nir ​​的转换解决方案。我想知道是否可以使用转换来完成。

      但有一个警告:不要在基于 ScrollView 的控件(例如 ListBox)上使用转换技巧,因为滚动条操作将与内容相反。只要您不是最终用户,就很有趣。 ;>

      【讨论】:

        猜你喜欢
        • 2015-09-27
        • 2015-06-21
        • 2013-09-05
        • 1970-01-01
        • 1970-01-01
        • 2010-11-21
        • 2023-03-09
        • 2012-06-06
        相关资源
        最近更新 更多