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

时间:2015-01-31 12:41:13

标签: wpf layout grid

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

enter image description here

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

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

<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"直接放在每个单独的网格中,并放在包含控件的面板上,没有效果。如何实现所有列共享宽度?

2 个答案:

答案 0 :(得分:6)

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

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

其他内容:您不需要ItemsControl周围的Stackpanel包装器,因为ItemsControl是唯一的子项。如果您需要调整ItemsControl使用的面板,请将其设置在Property 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的默认面板。

答案 1 :(得分:1)

基于Nautious&#39;回答我通过将两个ColumnDefinitions定义为资源并将所有列的Width属性绑定到这些主列定义的Width属性来解决问题#39;:

<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>

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