Wpf:网格:我如何共享列/行高度宽度?

时间:2010-07-30 08:16:32

标签: wpf

我有一个包含3列和5行的网格:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>

    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <Label Grid.Row="0" Grid.Column="0">Gas Volume Fraction</Label>
    <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=GasVolumeFraction}" MinWidth="40"></TextBox>
    <Label Grid.Row="0" Grid.Column="2">-</Label>

    <Label Grid.Row="1" Grid.Column="0">Density</Label>
    <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Density}" MinWidth="40"></TextBox>
    <Label Grid.Row="1" Grid.Column="2">kg/m3</Label>

    <Label Grid.Row="2" Grid.Column="0" Content="Curve speed" Style="{StaticResource curveSpeed}" ></Label>
    <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=Density}" Style="{StaticResource curveSpeed}" MinWidth="40"></TextBox>
    <Label Grid.Row="2" Grid.Column="2" Style="{StaticResource curveSpeed}">rpm</Label>

    <WrapPanel Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3">
        <RadioButton>Delta pressure</RadioButton>
        <RadioButton>Head</RadioButton>
    </WrapPanel>

    <WrapPanel Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="3">
        <RadioButton>Efficiency</RadioButton>
        <RadioButton>Power</RadioButton>
        <RadioButton>Torque</RadioButton>
    </WrapPanel>

</Grid>

文本框和单选按钮具有不同的空间要求,这使得行根据其内容呈现不同的高度。如何使行大小均匀,但不大于必要的大小?换句话说:对于包含文本框(我的网格中最大元素)的行,我想要设置高度=“自动”的高度,然后对所有行使用该高度。

4 个答案:

答案 0 :(得分:36)

我知道这是一个老问题,但我会回答那些在谷歌搜索时偶然发现的人。

使用Quartermeister提到的SharedSizeScope,实际上有一个非常简单的解决方案。

<Grid IsSharedSizeScope="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" SharedSizeGroup="groupName" />
        <RowDefinition Height="Auto" SharedSizeGroup="groupName" />
        <RowDefinition Height="Auto" SharedSizeGroup="groupName" />
    </Grid.RowDefinitions>

    ...
</Grid>

确保将Grid.IsSharedSizeScope设置为true,并确保每个RowDefinition具有相同的SharedSizeGroup,并且行应该是自动且大小相同的。这也适用于列。

答案 1 :(得分:13)

理想情况下,您可以使用具有星形大小的行并将网格设置为VerticalAlignment="Top",但遗憾的是,当网格大小调整为其内容时,星号大小不起作用。

不使用单个网格,而是使用UniformGrid作为垂直布局,使用嵌套网格控件进行水平布局。您可以在内部网格中的列上设置SharedSizeScope,以便在它们之间共享列大小。

<UniformGrid Rows="5" VerticalAlignment="Top" Grid.IsSharedSizeScope="True">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition SharedSizeGroup="B"/>
            <ColumnDefinition SharedSizeGroup="C"/>
        </Grid.ColumnDefinitions>

        <Label Grid.Column="0">Gas Volume Fraction</Label>
        <TextBox Grid.Column="1" Text="{Binding Path=GasVolumeFraction}" MinWidth="40"></TextBox>
        <Label Grid.Column="2">-</Label>
    </Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition SharedSizeGroup="B"/>
            <ColumnDefinition SharedSizeGroup="C"/>
        </Grid.ColumnDefinitions>

        <Label Grid.Column="0">Density</Label>
        <TextBox Grid.Column="1" Text="{Binding Path=Density}" MinWidth="40"></TextBox>
        <Label Grid.Column="2">kg/m3</Label>
    </Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="A"/>
            <ColumnDefinition SharedSizeGroup="B"/>
            <ColumnDefinition SharedSizeGroup="C"/>
        </Grid.ColumnDefinitions>
        <Label Grid.Column="0" Content="Curve speed" Style="{StaticResource curveSpeed}"></Label>
        <TextBox Grid.Column="1" Text="{Binding Path=Density}" Style="{StaticResource curveSpeed}" MinWidth="40"></TextBox>
        <Label Grid.Column="2" Style="{StaticResource curveSpeed}">rpm</Label>
    </Grid>
    <WrapPanel>
        <RadioButton>Delta pressure</RadioButton>
        <RadioButton>Head</RadioButton>
    </WrapPanel>
    <WrapPanel>
        <RadioButton>Efficiency</RadioButton>
        <RadioButton>Power</RadioButton>
        <RadioButton>Torque</RadioButton>
    </WrapPanel>
</UniformGrid>

答案 2 :(得分:1)

您可以使用绑定到最大TextBlock的ActualWidth和ActualHeight。

    <Grid x:Name="grid" ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="{Binding Path=ActualHeight, ElementName=biggestTB}"/>
            <RowDefinition Height="{Binding Path=ActualHeight, ElementName=biggestTB}"/>                        
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=biggestTB}"/>
            <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=biggestTB}"/>                        
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Grid.Column="0" x:Name="biggestTB" Text="biggest textblock content" TextWrapping="Wrap"/>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="content" TextWrapping="Wrap"/>
    </Grid>

答案 3 :(得分:0)

我的问题与上述问题类似,但略有不同,因为IsSharedSizeScope方法既没有为我解决问题,也没有通过ActualWidth进行绑定。因此,我发布了另一种解决方案,希望有人觉得有用。因此,这是我需要解决的问题:

我有一个应用程序,其中有一个带有拆分视图的控件-参见下面的蓝色部分-虽然我希望在显示屏中间有一个GridSplitter,但我想在单独的控件中实现蓝色部分位于其顶部的零件应在单独的组件中实施: enter image description here ...但是GridSplitter应该一直贯穿主视图并连接这两个区域,而用户无需对实际分离有所了解。我通过设置拖动TopSplitterMainSplitter的列宽来实现这一点。

此方法没有性能损失,并且可以处理大小为*的列。

事实证明,同步两个或多个GridSplitter(在这种情况下)实际上需要我们同步GridSplitter“调整大小”的列宽。拖到Top-或MainSplitter上,您会看到另一个区域的大小就像是一个拆分器一样:-)

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <Grid Grid.Row="0" Margin="3,3,3,0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" Name="TopColumnA"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*" Name="TopColumnB"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" Grid.Row="0"
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Background="AntiqueWhite"
                   Margin="0,0,3,3"
                   />

        <GridSplitter
            Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" Name="TopSplitter"
            HorizontalAlignment="Stretch"
            Background="Gray" Width="6"
            DragCompleted="GridSplitter_DragCompleted"
            DragDelta="MainSplitter_DragDelta"
            />

        <TextBlock Grid.Column="2" Grid.Row="0"
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Background="AntiqueWhite"
                   Margin="3,0,0,3"
                   />
    </Grid>

    <Grid Grid.Row="1" Margin="3,0,3,3">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" Name="MainColumnA"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*" Name="MainColumnB"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" Grid.Row="0"
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Background="Aqua"
                   Margin="0,0,3,0"
                   />

        <GridSplitter
            Grid.Column="1" Grid.Row="0" Grid.RowSpan="3" Name="MainSplitter"
            HorizontalAlignment="Stretch"
            Background="Black" Width="6"
            DragCompleted="GridSplitter_DragCompleted"
            DragDelta="MainSplitter_DragDelta"
            />

        <TextBlock Grid.Column="2" Grid.Row="0"
                   HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
                   Background="Aqua"
                   Margin="3,0,0,0"
                   />
    </Grid>
</Grid>

...这是后面的必需代码:

private void GridSplitter_DragCompleted(object sender, DragCompletedEventArgs e)
{
    if (sender == MainSplitter)
    {
        TopColumnA.Width = MainColumnA.Width;
        TopColumnB.Width = MainColumnB.Width;
    }
    else
    {
        if (sender == TopSplitter)
        {
            MainColumnA.Width = TopColumnA.Width;
            MainColumnB.Width = TopColumnB.Width;
        }
    }
}

private void MainSplitter_DragDelta(object sender, DragDeltaEventArgs e)
{
    if (sender == MainSplitter)
    {
        TopColumnA.Width = MainColumnA.Width;
        TopColumnB.Width = MainColumnB.Width;
    }
    else
    {
        if (sender == TopSplitter)
        {
            MainColumnA.Width = TopColumnA.Width;
            MainColumnB.Width = TopColumnB.Width;
        }
    }
}