如何将网格布局应用于嵌套的子元素?
How to apply a Grid layout to nested child elements?
几天来我一直在为这个问题绞尽脑汁。我正在尝试创建一个 UserControl
(s),它将允许我简化创建 I/O 表单的过程。在许多形式中,我需要具有如下结构的东西:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto">
<ColumnDefinition Width="*">
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition>
<RowDefinition>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="0" Text="..."/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="1" Text="..."/>
<TextBlock Grid.Column="0" Grid.Row="2" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="2" Text="..."/>
...
<Grid>
我想写的是这样的:
<mycontrols:ContainerControl>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
</mycontrols:ContainerControl>
RowControl
的 XAML 只是我喜欢的 TextBlock
和 TextBox
风格:
<TextBlock Text="{Binding Label}"/>
<TextBlock Text="{Binding Text}"/>
据我所知,这有一些问题:
1.- 为了使元素受网格布局影响,它必须是该网格的直接子元素。
2.- 行数是任意的。在 Grid
中,您需要指定每一行定义。
如果我能以某种方式让 Grid
的布局不仅影响直系子级而且影响嵌套子级,我想我可以做到这一点。如果你能想到的话,我也愿意用不同的方法来解决这个问题。
预期的最终行为是 StackPanel
和 Grid
的混合,即:
~ 可以添加任意数量的元素而无需定义行(只需堆叠它们)。
~ 容器分为两列,第一个取包含的最大元素的大小(auto),第二个取剩余的可用宽度(*)。
欢迎大家的帮助!提前致谢:)
您或许可以利用附加的 ColumnDefinition.SharedSizeGroup
and the Grid.IsSharedSizeScope
属性。尝试这样的事情:
<UserControl x:Class="CSharpTest.RowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="RowLabel"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Label}"/>
<TextBlock Text="{Binding Text}" Grid.Column="1"/>
</Grid>
</UserControl>
然后使用它:
<mycontrols:ContainerControl Grid.IsSharedSizeScope="True">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
</mycontrols:ContainerControl>
mycontrols:ContainerControl
可以是任何类型的容器(例如 StackPanel
、UniformGrid
等)。
在上面,每个 RowControl
的 Grid
的第一列将是统一的(它们都会增长以容纳最大的 Label
)。根据需要,您可能还需要在第二列上设置 SharedSizeGroup
(设置为 不同的 值,例如 "RowText")。
几天来我一直在为这个问题绞尽脑汁。我正在尝试创建一个 UserControl
(s),它将允许我简化创建 I/O 表单的过程。在许多形式中,我需要具有如下结构的东西:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto">
<ColumnDefinition Width="*">
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition>
<RowDefinition>
...
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Grid.Row="0" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="0" Text="..."/>
<TextBlock Grid.Column="0" Grid.Row="1" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="1" Text="..."/>
<TextBlock Grid.Column="0" Grid.Row="2" Text="..."/>
<TextBox Grid.Column="1" Grid.Row="2" Text="..."/>
...
<Grid>
我想写的是这样的:
<mycontrols:ContainerControl>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}">
</mycontrols:ContainerControl>
RowControl
的 XAML 只是我喜欢的 TextBlock
和 TextBox
风格:
<TextBlock Text="{Binding Label}"/>
<TextBlock Text="{Binding Text}"/>
据我所知,这有一些问题:
1.- 为了使元素受网格布局影响,它必须是该网格的直接子元素。
2.- 行数是任意的。在 Grid
中,您需要指定每一行定义。
如果我能以某种方式让 Grid
的布局不仅影响直系子级而且影响嵌套子级,我想我可以做到这一点。如果你能想到的话,我也愿意用不同的方法来解决这个问题。
预期的最终行为是 StackPanel
和 Grid
的混合,即:
~ 可以添加任意数量的元素而无需定义行(只需堆叠它们)。
~ 容器分为两列,第一个取包含的最大元素的大小(auto),第二个取剩余的可用宽度(*)。
欢迎大家的帮助!提前致谢:)
您或许可以利用附加的 ColumnDefinition.SharedSizeGroup
and the Grid.IsSharedSizeScope
属性。尝试这样的事情:
<UserControl x:Class="CSharpTest.RowControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=UserControl}}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="RowLabel"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Label}"/>
<TextBlock Text="{Binding Text}" Grid.Column="1"/>
</Grid>
</UserControl>
然后使用它:
<mycontrols:ContainerControl Grid.IsSharedSizeScope="True">
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
<mycontrols:RowControl Label="Some label" Text="{Binding SomeProperty}"/>
</mycontrols:ContainerControl>
mycontrols:ContainerControl
可以是任何类型的容器(例如 StackPanel
、UniformGrid
等)。
在上面,每个 RowControl
的 Grid
的第一列将是统一的(它们都会增长以容纳最大的 Label
)。根据需要,您可能还需要在第二列上设置 SharedSizeGroup
(设置为 不同的 值,例如 "RowText")。