【问题标题】:Wpf: Grid: How can i share column/row height width?Wpf:网格:我如何共享列/行高度宽度?
【发布时间】:2010-07-30 08:16:31
【问题描述】:

我有一个 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>

文本框和单选按钮具有不同的空间要求,这使得行根据其内容呈现不同的高度。我怎样才能使行大小均匀,但不大于必要的?换句话说:我希望为包含文本框(我的网格中最大的元素)的行设置与设置 Height="Auto" 相同的高度,然后为所有行使用该高度。

【问题讨论】:

  • 那么您希望 WrapPanel 会发生什么?如果你限制它们的高度,它们就必须有水平生长的空间。

标签: wpf


【解决方案1】:

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

这个问题实际上有一个非常简单的解决方案,使用 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,并且行应该是自动的且大小相同。这也适用于列。

【讨论】:

  • 当你这样做时,所有的行都会变成最大的吗?
  • @Dzyann:您可以省略 Height="Auto" 用于只占高度而不贡献其高度的行。
【解决方案2】:

理想情况下,您应该使用具有星号大小的行并将网格设置为VerticalAlignment="Top",但不幸的是,当网格大小与其内容相同时,星号大小不起作用。

不要使用单个 Grid,而是使用 UniformGrid 进行垂直布局,并使用嵌套的 Grid 控件进行水平布局。您可以在内部网格中的列上设置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>

【讨论】:

    【解决方案3】:

    您可以使用绑定到最大 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>
    

    【讨论】:

    • 在绑定到 ActualHeight 和 ActualWidth 时要小心:在很多情况下,控件的动态调整大小会导致测量和排列过程中的性能扼杀循环。
    【解决方案4】:

    我的问题与上述问题相似,但略有不同,因为IsSharedSizeScope 方法既没有为我解决问题,也没有使用 ActualWidth 绑定。所以,我发布了另一个解决方案,希望有人觉得这很有用。所以,这是我需要解决的问题:

    我有一个应用程序,其中我有一个带有拆分视图的控件 - 请参见下面的蓝色部分 - 虽然我喜欢在显示器中间有一个 GridSplitter,但我想在单独的控件中实现蓝色部分,而它上面的部分应该在一个单独的组件中实现: ...但是 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;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-03
      • 2011-01-20
      • 2020-06-03
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 1970-01-01
      • 2018-01-31
      相关资源
      最近更新 更多