在WPF中,有没有办法使StackPanel具有像Grid一样的对齐列?

时间:2012-08-29 12:17:27

标签: c# .net wpf grid stackpanel

例如,我可以这样做:

<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>

或者我可以这样做:

<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>

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

3 个答案:

答案 0 :(得分:4)

这里是一个我为了大致相同的目的而聚集在一起的课程 - 基本上我希望能够在左栏中放置一堆标签,并在不同类型(文本框,下拉列表等)上放置一些标签。右。

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

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)});
    }
}

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

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

答案 1 :(得分:3)

您可以在列上使用许多一行Gridssize sharing。在没有任何控制的情况下完成它会变得冗长,因此您可以在Grid.Columnattached property的派生中封装一些逻辑(例如创建列并分配ItemsControl)。

答案 2 :(得分:0)

这是使用其他答案所暗示的使用SharedSizeGroups对齐列的垂直StackPanel的一些可复制代码。它不需要任何代码隐藏,但是如果您希望动态创建面板,则可以添加它:

<Grid Grid.IsSharedSizeScope="True">

<StackPanel Orientation="Vertical" VerticalAlignment="Stretch" Grid.ColumnSpan="1">

    <!-- ROW 0 -->

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition SharedSizeGroup="FirstRow"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="FirstColumn" />
            <ColumnDefinition SharedSizeGroup="SecondColumn" />
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0">
            0-0 With extra width 
        </TextBlock>
        <TextBox Grid.Column="1">
            0,1
        </TextBox>
    </Grid>

    <!-- ROW 1 -->

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition SharedSizeGroup="FirstRow"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="FirstColumn"  />
            <ColumnDefinition SharedSizeGroup="SecondColumn"  />
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" HorizontalAlignment="Left">
            1-0
        </TextBlock>
        <TextBox Grid.Column="1">
            1,1 With extra width
        </TextBox>
    </Grid>

</StackPanel>

请注意,每列的SharedSizeGroup标签和最上方的网格均通过Grid.IsSharedSizeScope="True"启用这种逻辑。创建以下图像:

enter image description here