是否有更好的方法来布局表单上的标签/值对,而不是Grid或WrapPanel?

时间:2014-08-11 19:49:47

标签: c# wpf xaml

我正在寻找一种不那么繁琐的方法来布局键/值对(例如,标签说"名字"后跟带有名字的标签)。如果它只是一个简单的分组,我会把它扔进网格并完成。然而,布局2或3对,接着是一些类型的分组容器,有4或5对,后面是不同的分组容器等。

做这样的事情感觉非常麻烦:

<Grid>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width=".2*" />
         <ColumnDefinition Width="*" />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
         <RowDefinition />
         <RowDefinition />
      </Grid.RowDefinitions>

                <Label Grid.Column="0" Grid.Row="0" Content="Element ID:" HorizontalAlignment="Right" />
                <Label Grid.Column="1" Grid.Row="0" Content="{Binding Path=ElementId}" HorizontalAlignment="Left" FontWeight="Bold" />

                <Label Grid.Column="0" Grid.Row="1" Content="Element Description:" HorizontalAlignment="Right" />
                <Label Grid.Column="1" Grid.Row="1" Content="{Binding Path=ElementDescription}" HorizontalAlignment="Left" FontWeight="Bold" />                    
</Grid>

只是渲染出来:

_______元素ID:ABC123

元素描述:Spiffy!

当你有几个这样的部分时,尤其如此。

UniformGrid不允许您修复一列,以便Label可以右对齐。我尝试了StackPanel和WrapPanel的组合,但最终会产生大量的开销和大量的边缘摆弄。

有更好的方法吗?

4 个答案:

答案 0 :(得分:4)

据我所知,你应该可以做这样的事情,当你有很多这样的东西时非常方便;

<UniformGrid Columns="2">

  <UniformGrid.Resources>

    <!-- Set your properties once, in one place, 
         and control your children like a good parent. -->

    <Style TargetType="Label">
      <Setter Property="HorizontalAlignment" Value="Right"/>
    </Style>
    <Style TargetType="TextBlock">
      <Setter Property="FontWeight" Value="Bold"/>
      <!-- If you want to control your cell width so the descriptions doesn't
           offset the size of the ID's you could just enable/edit these setters.
      <Setter Property="TextWrapping" Value="Wrap"/>
      <Setter Property="MaxWidth" Value="150"/>
      -->
    </Style>

  </UniformGrid.Resources>

  <Label Content="Element ID:"/>
  <TextBlock Text="{Binding Path=ElementId}"/>

  <Label Content="Element Description:"/>
  <TextBlock Text="{Binding Path=ElementDescription}"/>

  <!-- etc, etc, etc. -->

</UniformGrid>

PS - 避免使用Label并使用TextBlock,除非它真的有益,因为Label比TextBlock重。

希望这会有所帮助,欢呼。

答案 1 :(得分:3)

您可以将Autogrid用于xaml,如下所示:

<AutoGrid RowCount="2" RowHeight="35" Columns="100,auto">
  <Label />
  <TextBox />
  <Label />
  <TextBox />
</AutoGrid>

答案 2 :(得分:1)

您可以创建shared size group,它允许单独的Grid中的多个列具有相同的大小。然后,您可以使用ItemsControl附加属性设置为Grid.IsSharedSizeScope的{​​{1}}来显示您的商品。它可能有点沉重,因为它为每一行创建了一个新的true,但这是我能够获得的结果(full code here):

enter image description here

在我的视图模型中,我创建了一个基类Grid和两个子类RowDividerRow。主视图模型有KeyValueRow行,填充方式如下:

ObservableCollection<Row>

XAML定义绑定到Rows的ItemsControl并将自己定义为共享大小范围:

public class ViewModel : BaseVM
{
    ObservableCollection<Row> _rows = new ObservableCollection<Row> ();
    public ObservableCollection<Row> Rows { get { return _rows; } }

    public ViewModel()
    {
        _rows.Add (new DividerRow () { Title = "Fruit" });
        _rows.Add (new KeyValueRow () { Key = "Apple", Value = "$1.01" });
        _rows.Add (new KeyValueRow () { Key = "Apricot", Value = "$2.01" });
        _rows.Add (new KeyValueRow () { Key = "Pineapple", Value = "$3.01" });

        _rows.Add (new DividerRow () { Title = "Meat" });
        _rows.Add (new KeyValueRow () { Key = "Bacon", Value = "$4.01" });
        _rows.Add (new KeyValueRow () { Key = "Ground-Turkey", Value = "$5.01" });
        _rows.Add (new KeyValueRow () { Key = "Sausage", Value = "$6.01" });
        _rows.Add (new KeyValueRow () { Key = "Andmorereallytastystuff", Value = "$7.01" });
    }
}

每个单独的行都是使用窗口资源字典中的无名,基于类型的<Canvas> <ItemsControl ItemsSource="{Binding Rows}" Margin="50" Grid.IsSharedSizeScope="True" /> </Canvas> 来定义的。分隔线并不是非常相互影响的。它只是DataTemplate

TextBlock

使列具有相同宽度的有趣部分位于行的模板中,该列将列定义为<DataTemplate DataType="{x:Type l:DividerRow}"> <TextBlock HorizontalAlignment="Stretch" TextAlignment="Center" FontWeight="Bold" Padding="5,5,5,0" Margin="0,10,0,0" Background="LightBlue" Text="{Binding Title}" /> </DataTemplate> 的A和B.

SharedSizeGroup

请注意,如果<DataTemplate DataType="{x:Type l:KeyValueRow}"> <Grid > <Grid.ColumnDefinitions> <ColumnDefinition SharedSizeGroup="A" Width="Auto" /> <ColumnDefinition SharedSizeGroup="B" Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Column="0" HorizontalAlignment="Right" Text="{Binding Key}" /> <TextBlock Grid.Column="1" Margin="5,0,5,0" FontWeight="Bold" Text="{Binding Value}" /> </Grid> </DataTemplate> 中没有Grid.IsSharedSizeScope,则无法正常使用。希望有所帮助!很抱歉格式化详细,但我希望XAML与提供的示例图像相匹配。

答案 3 :(得分:0)

为每种标签类型创建一种样式,用于定义对齐和字体粗细。这样可以减少重复次数,并为您提供单点管理外观。

或者,在视图模型中将它们显示为字典,并使用带有模板的项控件来显示它们。