如何将网格布局应用于嵌套的子元素?

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 只是我喜欢的 TextBlockTextBox 风格:

   <TextBlock Text="{Binding Label}"/>
   <TextBlock Text="{Binding Text}"/>

据我所知,这有一些问题:

1.- 为了使元素受网格布局影响,它必须是该网格的直接子元素。

2.- 行数是任意的。在 Grid 中,您需要指定每一行定义。

如果我能以某种方式让 Grid 的布局不仅影响直系子级而且影响嵌套子级,我想我可以做到这一点。如果你能想到的话,我也愿意用不同的方法来解决这个问题。

预期的最终行为是 StackPanelGrid 的混合,即:

~ 可以添加任意数量的元素而无需定义行(只需堆叠它们)。

~ 容器分为两列,第一个取包含的最大元素的大小(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 可以是任何类型的容器(例如 StackPanelUniformGrid 等)。

在上面,每个 RowControlGrid 的第一列将是统一的(它们都会增长以容纳最大的 Label)。根据需要,您可能还需要在第二列上设置 SharedSizeGroup(设置为 不同的 值,例如 "RowText")。