WPF:StackPanel与FirstChildFill?

And*_*ita 6 c# wpf layout fill

我想要一种逻辑和简单的方法来生成一个布局,其中一个控件集要填充,其余的要停靠.我可以用:

<DockPanel LastChildFill="True">
  <Button Content="3" DockPanel.Dock="Bottom" />
  <Button Content="2" DockPanel.Dock="Bottom" />
  <Button Content="1" />
</DockPanel>
Run Code Online (Sandbox Code Playgroud)

但它的使用不是很直观.我也可以这样做:

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
  <Button Content="1" Grid.Row="0" />
  <Button Content="2" Grid.Row="1" />
  <Button Content="3" Grid.Row="2" />
</Grid>
Run Code Online (Sandbox Code Playgroud)

但它也有很多xaml.我真正想要的是这样的:

<StackPanel Fill="None|First|Last">
  <Button Content="1" />
  <Button Content="2" />
  <Button Content="3" />
</StackPanel>
Run Code Online (Sandbox Code Playgroud)

如何在不必像DockPanel那样反转项目而不使用固定数量的行和附加属性的情况下实现这一点?

Wil*_*ean 3

您始终可以使用不同的对接规则编写自己的面板。您可以使用标准 DockPanel 实现(可在框架源代码中找到 - 它看起来不是很复杂)并使用您喜欢的规则创建类似的东西。您甚至可以创建一个派生自 DockPanel 并覆盖 ArrangeOverride 的类。

但就我个人而言,我只会使用停靠面板,它完全符合您的要求,只是您不喜欢它关于哪个成员可以填充的规则。

如果您插入/删除行,IME 网格会遇到可怕的维护问题,因为您会发现自己无休止地调整行号 - DockPanel 在这方面要容易得多。

更新:

给你,我已经拒绝了你自己做这件事的乐趣 - 这只是框架源代码的缩减/反转版本:

public class BottomDockingPanel : DockPanel
{
    protected override Size ArrangeOverride(Size arrangeSize)
    {
        UIElementCollection children = InternalChildren;
        int totalChildrenCount = children.Count;

        double accumulatedBottom = 0;

        for (int i = totalChildrenCount-1; i >=0 ; --i)
        {
            UIElement child = children[i];
            if (child == null) { continue; }

            Size childDesiredSize = child.DesiredSize;
            Rect rcChild = new Rect(
                0,
                0,
                Math.Max(0.0, arrangeSize.Width - (0 + (double)0)),
                Math.Max(0.0, arrangeSize.Height - (0 + accumulatedBottom)));

            if (i > 0)
            {
                accumulatedBottom += childDesiredSize.Height;
                rcChild.Y = Math.Max(0.0, arrangeSize.Height - accumulatedBottom);
                rcChild.Height = childDesiredSize.Height;
            }

            child.Arrange(rcChild);
        }
        return (arrangeSize);
    }
}
Run Code Online (Sandbox Code Playgroud)