Wpf: Grid: How can i share column/row height width?
I have a grid with 3 columns and 5 rows:
<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">Densit开发者_Go百科y</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>
The textboxes and radiobuttons have different space requirements, which makes the rows render with different heights based on their content. How can I make the rows evenly sized, but not larger than whats necessary? In other words: I want the same height as setting Height="Auto" for a row which contains a textbox (the biggest element in my grid) and then use that height for all the rows.
I know this is an old question, but I'll answer for anyone who stumbles across this while googling.
There's actually a very simple solution to this problem, using the SharedSizeScope mentioned by Quartermeister.
<Grid IsSharedSizeScope="True">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" SharedSizeGroup="groupName" />
<RowDefinition Height="Auto" SharedSizeGroup="groupName" />
<RowDefinition Height="Auto" SharedSizeGroup="groupName" />
</Grid.RowDefinitions>
...
</Grid>
Just make sure you set Grid.IsSharedSizeScope to true, and make sure that each RowDefinition has the same SharedSizeGroup, and the rows should be auto and equally sized. This works for columns as well.
Ideally you would use rows with star sizing as you have and set the Grid to VerticalAlignment="Top"
, but unfortunately star sizing doesn't work when the grid sizes to its content.
Instead of using a single Grid, use a UniformGrid for the vertical layout with nested Grid controls for horizontal layout. You can set a SharedSizeScope on the columns in the inner grids so that the column sizing is shared between them.
<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>
You can use binding to ActualWidth and ActualHeight of your biggest TextBlock.
<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>
My problem is similar to the above question but slightly different because neither the IsSharedSizeScope
approach solved it for me nor the Binding with ActualWidth. So, I post another solution hoping someone finds this useful. So, here is the problem I needed to solve:
I have an application in which I have a control with a split view - see blue part below - and while I like to have a GridSplitter in the middle of the display I want to implement the blue part in a seperate control while the part on top of it should be implemented in a seperated assembly:
...but the GridSplitter should go all the way across the main view and connect both areas without the user having an idea about the actual seperation. I accomplished this by setting the columns width whenever theTopSplitter
or the MainSplitter
is dragged.
This approach has no performance penality and works with '*' sized columns.
It turnes out that synchronizing two or more GridSplitters (as in this case) requires us in fact to synchronize the columns width that are 'resized' by the GridSplitter. Drag on the Top- or MainSplitter and you'll see that the other area resizes as if this was one splitter :-)
<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>
...and here is the required code behind:
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;
}
}
}
精彩评论