Рассмотрим следующий XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Button Content="Button" HorizontalAlignment="Left"/>
<Grid Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Content="B" Margin="5"/>
<Button Content="Button" Grid.Column="1" Margin="5"/>
</Grid>
</Grid>
В приведенном выше примере все значения ColumnDefinition
, кроме одного, используют значение по умолчанию для Width
, которое равно "*"
, то есть "размер звезды". Единственным исключением является столбец, содержащий вложенный элемент управления Grid
, который установлен на "Auto"
.
Как я ожидаю, это будет работать следующим образом:
- Внешний
Grid
определяет второй столбец в соответствии с потребностями его содержимого, а затем присваивает оставшуюся ширину элемента управления первому столбцу. - Внутренний
Grid
равномерно распределяет доступное пространство к двум столбцам. В конце концов, оба они настроены на использование размера звезды, а размер звезды должен установить свойствоGridLength
(ширина в этом случае) для взвешенного распределения доступного пространства. Минимальный размер макета для этого внутреннегоGrid
(необходимого для внешнегоGrid
для вычисления ширины его второго столбца) представляет собой сумму столбцов с равномерным распределением ширины, звездчатого размера (то есть в этом случае, в два раза больше ширину столбца с самым широким контентом).
Но вместо этого ширины столбцов для вложенной сетки устанавливаются в соответствии с вычисленным минимальным размером каждой кнопки без видимой взвешенной зависимости между двумя столбцами звездного размера (для ясности показаны линии сетки):
Он работает как ожидалось, если у меня нет внешней сетки, т.е. просто сделайте внутреннюю сетку единственной сеткой в окне:
Два столбца вынуждены иметь одинаковый размер, и тогда, конечно, левая кнопка растягивается, чтобы соответствовать размеру его содержащей ячейки (именно это я хочу & hellip; конечная цель состоит в том, чтобы эти две кнопки имели та же ширина, с столбцами сетки, обеспечивающие макет для выполнения этого).
В этом конкретном примере я могу использовать UniformGrid
как обход, чтобы обеспечить равномерное распределение ширины столбцов. Вот как я хочу, чтобы он действительно выглядел (UniformGrid
не имеет свойства ShowGridLines
, поэтому вам просто нужно представить воображаемую линию между двумя правильными кнопками):
Но я действительно хотел бы более подробно понять, как это сделать, так что в более сложных сценариях я мог бы использовать размер звезды в вложенном элементе управления Grid
.
Кажется, что каким-то образом, находясь внутри ячейки другого элемента управления Grid
, изменяется способ определения размера звезды для внутреннего элемента управления Grid
(или предотвращения изменения размера звезды). Но почему это должно быть? Я упускаю (еще раз) какое-то эзотерическое правило размещения WPF, которое объясняет это как поведение "по дизайну"? Или это просто ошибка в рамках?
Update:
Я понимаю, что ответ Бена означает, что размер звезды должен распределять только оставшееся пространство после учета минимальных размеров для каждого столбца. Но это не то, что можно увидеть в других сценариях.
Например, если столбец, содержащий внутреннюю сетку, был определен явно, то использование значения размера звезды для внутренних столбцов сетки приводит к равномерному распределению столбцов, как и ожидалось.
т.е. этот XAML:
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<!--
<ColumnDefinition Width="Auto"/>
-->
<ColumnDefinition Width="60"/>
</Grid.ColumnDefinitions>
<Button Content="Button" HorizontalAlignment="Left"/>
<Grid Grid.Column="1" ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Content="B" Margin="5"/>
<Button Content="Button" Grid.Column="1" Margin="5"/>
</Grid>
</Grid>
производит этот вывод:
Другими словами, в худшем случае я ожидаю, что WPF сначала вычислит минимальный размер внутренней сетки, не учитывая размер звезды (например, если короткая кнопка занимает 10 пикселей, а длинная кнопка - 70, то общая ширина будет равна 80), а затем равномерно распределить ширину столбцов (т.е. в примере 10/70 каждый столбец будет содержать 40 пикселей, усекается более длинная кнопка, аналогичная приведенному выше изображению).
Почему размер звезды иногда равномерно распределяет ширину по столбцам, а иногда нет?
Обновление # 2:
Вот простой пример, который ясно и драматично показывает, как WPF относится к размеру звезд по-разному в зависимости от того, будет ли он вычислять ширину Grid
или вы:
<Window x:Class="TestGridLayout2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight"
Title="MainWindow">
<Window.Resources>
<Style TargetType="Border">
<Setter Property="BorderBrush" Value="Black"/>
<Setter Property="BorderThickness" Value="1"/>
</Style>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="24"/>
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="3*"/>
</Grid.ColumnDefinitions>
<Border Grid.Column="0"/>
<Border Grid.Column="1"/>
<StackPanel>
<TextBlock Text="Some text -- one"/>
<TextBlock Text="Some text -- two"/>
<TextBlock Text="Some text -- three"/>
</StackPanel>
<StackPanel Grid.Column="1">
<TextBlock Text="one"/>
<TextBlock Text="two"/>
<TextBlock Text="three"/>
</StackPanel>
</Grid>
</Window>
При запуске программы вы увидите следующее:
WPF проигнорировал размер звезды, установив минимальную ширину столбца. Если вы просто нажимаете на границу окна, как если бы для изменения размера окна (вам даже не нужно перетаскивать границу в любом месте), макет Grid
будет переделан, и вы получите следующее:
В этот момент применяется значение размера звезды (как и следовало ожидать), и столбцы распределяются в соответствии с объявлениями XAML.