在WPF网格中的行和列中“转置”控件

时间:2011-02-16 16:48:30

标签: wpf xaml grid

我有一个wrappanel,它充当一组定义为

的控件的容器
<WrapPanel Orientation="Horizontal">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition  />
      <RowDefinition   />
      <RowDefinition   />
    </Grid.RowDefinitions>
    <Label Grid.Row="0">test1</Label>
    <ComboBox Grid.Row="1" MinWidth="60"></ComboBox>
    <ComboBox Grid.Row="2" MinWidth="60"></ComboBox>
  </Grid>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition  />
      <RowDefinition   />
      <RowDefinition   />
    </Grid.RowDefinitions>
    <Label Grid.Row="0">test1</Label>
    <TextBox Grid.Row="1" MinWidth="60"></TextBox>
    <TextBox Grid.Row="2" MinWidth="60"></TextBox>
  </Grid>
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition  />
      <RowDefinition   />
      <RowDefinition   />
    </Grid.RowDefinitions>
    <Label Grid.Row="0">test1</Label>
    <ComboBox Grid.Row="1" MinWidth="60"></ComboBox>
    <ComboBox Grid.Row="2" MinWidth="60"></ComboBox>
  </Grid>           
</WrapPanel>

所以基本上它包含多个网格,每个网格有3行,网格中的每个单元格都有一个控件。 我希望用户能够“转置”此布局,以使包裹带现在具有垂直方向,网格现在是3列网格。因此,如果手动完成,xaml看起来像

<WrapPanel Orientation="Vertical">
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition  />
      <ColumnDefinition  />
      <ColumnDefinition  />
    </Grid.ColumnDefinitions>
    <Label Grid.Column="0">test1</Label>
    <ComboBox Grid.Column="1" MinWidth="60"></ComboBox>
    <ComboBox Grid.Column="2" MinWidth="60"></ComboBox>
  </Grid>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition  />
      <ColumnDefinition  />
      <ColumnDefinition  />
    </Grid.ColumnDefinitions>
    <Label Grid.Column="0">test1</Label>
    <TextBox Grid.Column="1" MinWidth="60"></TextBox>
    <TextBox Grid.Column="2" MinWidth="60"></TextBox>
  </Grid>
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition  />
      <ColumnDefinition  />
      <ColumnDefinition  />
    </Grid.ColumnDefinitions>
    <Label Grid.Column="0">test1</Label>
    <ComboBox Grid.Column="1" MinWidth="60"></ComboBox>
    <ComboBox Grid.Column="2" MinWidth="60"></ComboBox>
  </Grid>           
</WrapPanel>
  1. 最好的方法是什么?
  2. 有没有办法做到这一点并避免代码隐藏?

2 个答案:

答案 0 :(得分:1)

您可以使网格始终包含3行和3列。当您使用“行”时,您需要添加Grid.ColumnSpan="3"(为了使其保持相同),并在转置时使用RowSpan

为了进行转置,在代码中处理它很可能是最简单的选择。通过在您的商品上调用Grid.GetRow / SetRow /等,您可以轻松进行转置。

为了避免将其放入后面的代码中,您可以创建一个attached property来处理网格本身。这将允许您将属性绑定到ViewModel中的布尔值或枚举,并在运行时基于业务逻辑执行转置。

答案 1 :(得分:0)

如果你可以换掉StackPanels的网格

    <WrapPanel x:Name="Wrap"
               Orientation="Vertical">
        <StackPanel Orientation="{Binding Orientation, ElementName=Wrap, Converter={StaticResource InverseOrientationConverter}}">
            <Label>test1</Label>
            <ComboBox MinWidth="60"></ComboBox>
            <ComboBox MinWidth="60"></ComboBox>
        </StackPanel>
        <StackPanel Orientation="{Binding Orientation, ElementName=Wrap, Converter={StaticResource InverseOrientationConverter}}">
            <Label>test1</Label>
            <TextBox MinWidth="60"></TextBox>
            <TextBox MinWidth="60"></TextBox>
        </StackPanel>
        <StackPanel Orientation="{Binding Orientation, ElementName=Wrap, Converter={StaticResource InverseOrientationConverter}}">
            <Label>test1</Label>
            <ComboBox MinWidth="60"></ComboBox>
            <ComboBox MinWidth="60"></ComboBox>
        </StackPanel>
    </WrapPanel>

然后你可以使用这个转换器

public class InverseOrientationConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!(value is Orientation))
            throw new ApplicationException();

        Orientation orientation = (Orientation)value;

        if (orientation == Orientation.Horizontal)
            return Orientation.Vertical;

        return Orientation.Horizontal;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}