在多个网格之间共享列宽

Sharing column widths between multiple grids

我有以下 XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid Grid.Row="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="Header 1" />
        <TextBlock Grid.Column="1" Text="Header 2" />
    </Grid>
    <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <ItemsControl ItemsSource="{Binding SomeList}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <TextBox Grid.Column="0" Text="{Binding Value1}" />
                        <TextBox Grid.Column="1" Text="{Binding Value2}" />
                        <Button Grid.Column="2" Content="Button" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>    
    </ScrollViewer>
</Grid>

我想实现这样的目标:

Header 1              |Header 2              |             <--   this is the top grid
------------------------------------------------------
Value 1.1             |Value 1.2             |[Button]         |
Value 2.1             |Value 2.2             |[Button]     <-- | this is the scroll viewer
Value 3.1             |Value 3.2             |[Button]         |

这看起来类似于具有固定 header 行的数据网格。我不能使用实际的 DataGrid,因为在实际的应用程序中,"Header 1" 和 "Header 2" 实际上不是简单的网格文本 header,而是具有相当复杂标记的可交互元素。主要问题是如何实现所有三列的宽度同步?最后一列的大小应为该列中最宽的按钮,而前两列应按 50/50 的比例共享剩余的 space。感觉这可以使用 SharedSizeGroup 属性 来实现,但我不知道具体如何实现。

我想我知道怎么做了:

<Grid Grid.IsSharedSizeScope="True">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid Grid.Row="0" Width="{Binding ActualWidth, ElementName=itemsControl}"
          HorizontalAlignment="Left">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="Auto" SharedSizeGroup="ButtonColumn" />
        </Grid.ColumnDefinitions>
        <TextBlock Grid.Column="0" Text="Header 1" />
        <TextBlock Grid.Column="1" Text="Header 2" />
    </Grid>
    <ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
        <ItemsControl Name="itemsControl" ItemsSource="{Binding SomeList}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" SharedSizeGroup="ButtonColumn" />
                        </Grid.ColumnDefinitions>
                        <TextBox Grid.Column="0" Text="{Binding Value1}" />
                        <TextBox Grid.Column="1" Text="{Binding Value2}" />
                        <Button Grid.Column="2" Content="Button" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>    
    </ScrollViewer>
</Grid>
  1. Grid.IsSharedSizeScope="True"SharedSizeGroup="ButtonColumn" 同步最后一列。
  2. Width="*" 以 50/50 的比例将剩余的 space 拆分为前两列。
  3. Width="{Binding ActualWidth, ElementName=itemsControl}" 将顶部 header 网格的宽度与下方 ItemsControl 的宽度同步,滚动条显示或隐藏时可以更改。
  4. HorizontalAlignment="Left" 将 header 网格向左推,使其与下面的 ItemsControl 对齐。