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>
Для текстовых полей и радиокнопок предъявляются разные требования к пространству, поэтому строки отображаются с разной высотой в зависимости от их содержимого. Как сделать так, чтобы строки были одинакового размера, но не больше, чем нужно? Другими словами: я хочу получить ту же высоту, что и параметр Height="Auto" для строки, которая содержит текстовое поле (самый большой элемент в моей сетке), а затем использовать эту высоту для всех строк.
3 ответа
В идеале вы должны использовать строки со звездообразным размером и установить для Grid значение VerticalAlignment="Top"
, но, к сожалению, размер звезды не работает, когда размер сетки соответствует ее содержанию.
Вместо использования одной сетки, используйте 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>
Я знаю, что это старый вопрос, но я отвечу за всех, кто сталкивается с этим, когда гуглит.
На самом деле существует очень простое решение этой проблемы с использованием SharedSizeScope, упомянутого Quartermeister.
<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, а строки должны быть автоматически и иметь одинаковый размер. Это работает и для столбцов.
Вы можете использовать привязку к ActualWidth и ActualHeight вашего самого большого 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>
Моя проблема похожа на вопрос выше, но немного отличается, потому что ни IsSharedSizeScope
подход решил это для меня, ни Binding с ActualWidth. Итак, я публикую другое решение, надеясь, что кто-то найдет это полезным. Итак, вот проблема, которую мне нужно было решить:
У меня есть приложение, в котором у меня есть элемент управления с разделенным видом - см. Синюю часть ниже - и хотя мне нравится иметь GridSplitter в середине экрана, я хочу реализовать синюю часть в отдельном элементе управления, в то время как часть сверху это должно быть реализовано в отдельной сборке: ... но GridSplitter должен пройти весь основной вид и соединить обе области, чтобы у пользователя не было представления о фактическом разделении. Я сделал это, установив ширину столбцов всякий раз, когда TopSplitter
или MainSplitter
тащат
Этот подход не требует снижения производительности и работает со столбцами размера "*".
Оказывается, что синхронизация двух или более GridSplitters (как в этом случае) фактически требует от нас синхронизации ширины столбцов, которые "изменяются" с помощью 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;
}
}
}