在模板中定义的网格之间共享列宽

Sharing column width between grids defined in a template

我正在尝试布置几个控件:

浅灰色垂直线是网格分隔线。 table 中的每一行都是一个三列的网格,左边是标签,中间是拆分器,右边是控件,包括文本框和图像。

我希望所有列都对齐。这是我为每一行使用的数据模板:

<DataTemplate x:Key="PropertyLineTemplate">
    <Grid Margin="0,0,0,1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="Name"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition SharedSizeGroup="Value"/>
        </Grid.ColumnDefinitions>

        <TextBlock 
            Grid.Column="0"            
            VerticalAlignment="Center"
            Text="{Binding Title}" /> 

        <GridSplitter Grid.Column="1" Width="2"/>

        <SomeUserControl
            Grid.Column="2"               
            Content="{Binding}"                
            Margin="4, 0, 0, 0"/>
    </Grid>
</DataTemplate>

以及视图本身的模板:

<DataTemplate DataType="{x:Type vm:PropertiesViewModel}">
    <DockPanel>            
        <!-- Properties -->
        <ScrollViewer>
            <StackPanel Margin="10">
                <ItemsControl ItemsSource="{Binding Properties}"
                        ItemTemplate="{StaticResource PropertyLineTemplate}" />
            </StackPanel>
        </ScrollViewer>
    </DockPanel>
</DataTemplate>

以及两者的用法:

<ContentControl Content="{Binding SelectedItem}" Grid.IsSharedSizeScope="True">          
</ContentControl>

其中 SelectedItem 的类型为 PropertiesViewModel

我还尝试将 Grid.IsSharedSizeScope="True" 直接放置在每个单独的网格中以及包含控件的面板上,但没有效果。如何实现所有列共享宽度?

Grid.IsSharedSizeScope 应该设置在 Grid 的第一个父 ItemsControl 上,在您的情况下它将是 ViewModel 模板中的 ItemsControl。然后将调整列宽。

但是,如果您移动一个 GridSplitter,则它只会调整该行,而不会调整其他行(如果您需要调整大小,请参阅 WPF SharedSizeGroup GridSplitter Issue 了解潜在的解决方案。)

其他内容:您不需要围绕 ItemsControl 的 Stackpanel 包装器,因为 ItemsControl 是唯一的子控件。如果您需要调整 ItemsControl 使用的面板,则将其设置在 属性 ItemsPanel 上,如下所示:

<ItemsControl ItemsSource="{Binding Properties}"
              Grid.IsSharedSizeScope="True"
              ItemTemplate="{StaticResource PropertyLineTemplate}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel/> <!-- Or <WrapPanel/> or <UniformGrid/> etc. -->
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

但是,Stackpanel 是 ItemsControl 的默认面板。

根据 Nautious 的回答,我通过将两个 ColumnDefinitions 定义为资源并将所有相关列的 Width 属性 绑定到 Width 属性 其中 'master column definitions':

<ColumnDefinition x:Key="MasterColumnDefinition" />

<ColumnDefinition x:Key="MasterColumnDefinition2" />

<DataTemplate x:Key="PropertyLineTemplate">
     <Grid Margin="0,0,0,1">
          <Grid.ColumnDefinitions>
              <ColumnDefinition Width="{Binding Source={StaticResource MasterColumnDefinition}, Path=Width, Mode=TwoWay}"/>
              <ColumnDefinition Width="Auto"/>
              <ColumnDefinition Width="{Binding Source={StaticResource MasterColumnDefinition2}, Path=Width, Mode=TwoWay}"/>
          </Grid.ColumnDefinitions>

          ...
    </Grid>
</DataTemplate>

可能有点老套,但它很简单而且有效。但是,并不是说此解决方案的 shared size scope 是定义资源的范围。 IE。将这些模板放在应用程序的资源中将导致应用程序中的所有列同步调整大小。