在 WPF 中,有没有办法让 StackPanel 像网格一样具有对齐的列?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12177749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 05:08:47  来源:igfitidea点击:

In WPF, is there a way to make a StackPanel with aligned columns like a Grid?

c#.netwpfgridstackpanel

提问by Matt

For example I could do something like this:

例如,我可以做这样的事情:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Width="Auto">
        <RowDefinition Width="Auto">
        <RowDefinition Width="Auto">
    </Grid.RowDefinitions>
    <TextBlock Grid.Row="0" Grid.Column="0">Header 1</TextBlock>
    <TextBox Grid.Row="0" Grid.Column="1" MaxLines="1" />
    <Button Grid.Row="0" Grid.Column="2">Send</Button>
    <Button Grid.Row="0" Grid.Column="3">Save</Button>
    <TextBlock Grid.Row="1" Grid.Column="0">Header 2</TextBlock>
    <TextBox Grid.Row="1" Grid.Column="1" MaxLines="1" />
    <Button Grid.Row="1" Grid.Column="2">Send</Button>
    <Button Grid.Row="1" Grid.Column="3">Save</Button>
    <TextBlock Grid.Row="2" Grid.Column="0">Header 3</TextBlock>
    <TextBox Grid.Row="2" Grid.Column="1" MaxLines="1" />
    <Button Grid.Row="2" Grid.Column="2">Send</Button>
    <Button Grid.Row="2" Grid.Column="3">Save</Button>
</Grid>

Or I could do something like this:

或者我可以做这样的事情:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock>Header 1</TextBlock>
        <TextBox MaxLines="1" />
        <Button>Send</Button>
        <Button>Save</Button>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock>Header 2</TextBlock>
        <TextBox MaxLines="1" />
        <Button>Send</Button>
        <Button>Save</Button>
    </StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock>Header 3</TextBlock>
        <TextBox MaxLines="1" />
        <Button>Send</Button>
        <Button>Save</Button>
    </StackPanel>
<StackPanel>

Except that I want to be able to easily manipulate the rows (add new rows, move rows around, etc.) just like in the StackPanel, while keeping the columns aligned properly just like in the Grid.

除了我希望能够像在 StackPanel 中一样轻松地操作行(添加新行、移动行等),同时像在网格中一样保持列正确对齐。

采纳答案by H.B.

You could use many one-row Gridswith size sharingon the columns. It gets verbose when done without any controls, so you could encapsulate some logic (like creating columns and assigning Grid.Column) in a derivative of ItemsControlor an attached propertyfor example.

您可以在列上使用许多Grids具有大小共享的单行。在没有任何控件的情况下完成时它会变得冗长,因此您可以将一些逻辑(如创建列和分配Grid.Column)封装在例如的派生属性ItemsControl附加属性中。

回答by Overlord Zurg

Here's a class I just threw together for approximately the same purpose - essentially I wanted to be able to put a bunch of labels in the left column and values of different types (text box, dropdown, etc) on the right.

这是我为了大致相同的目的而拼凑在一起的一个类 - 基本上我希望能够在左列中放置一堆标签,并在右侧放置不同类型(文本框、下拉列表等)的值。

It only has two columns, but it could be adapted to different numbers.

它只有两列,但可以适应不同的数字。

public class LabelValueGrid : Grid
{
    public LabelValueGrid()
        : base()
    {
        ColumnDefinitions.Add(new ColumnDefinition());
        ColumnDefinitions.Add(new ColumnDefinition());
        ColumnDefinitions[0].Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Auto);
        ColumnDefinitions[1].Width = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star);
    }

    protected override void OnVisualChildrenChanged(System.Windows.DependencyObject visualAdded, System.Windows.DependencyObject visualRemoved)
    {
        base.OnVisualChildrenChanged(visualAdded, visualRemoved);

        int curRow = -1;
        int curCol = 1;

        RowDefinitions.Clear();

        if (Children != null)
            foreach (System.Windows.UIElement curChild in Children)
            {
                if (curCol == 0)
                    curCol = 1;
                else
                {
                    curCol = 0;
                    curRow++;
                    RowDefinitions.Add(new RowDefinition() {Height = new System.Windows.GridLength(1, System.Windows.GridUnitType.Auto)});
                }

                Grid.SetRow(curChild, curRow);
                Grid.SetColumn(curChild, curCol);
            }

        RowDefinitions.Add(new RowDefinition() {Height = new System.Windows.GridLength(1, System.Windows.GridUnitType.Star)});
    }
}

I can use this like a grid, except I just list the controls and then it alternates the columns automatically:

我可以像网格一样使用它,除了我只列出控件然后它会自动交替列:

<local:LabelValueGrid>
    <TextBlock Text="Label1"/>
    <TextBox Name="value1"/>
    <TextBlock Text="Label2"/>
    <TextBox Name="value2"/>
</local:LabelValueGrid>