开发者

'Transposing' controls in rows and columns in a WPF Grid

I have a wrappanel that acts as a container for a group of controls defined as

<WrapPanel Orientation="Horizontal">
  <Grid>
    <Grid.RowDe开发者_如何学运维finitions>
      <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>

So basically it wraps multiple grids that have 3 rows each, and every cell in the grid has a control. I want the user to have the ability to 'transpose' this layout so that the wrappanel now has a vertical orientation and the grid is now a 3 column grid. So if done manually the xaml would look like

<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. Whats the best way to achieve this?
  2. Is there any way to do this and avoid codebehind?


You could make your grid always contain 3 rows and 3 columns. When you are using "rows", you would need to add Grid.ColumnSpan="3" (in order to keep this looking the same), and when transposed, use RowSpan.

In order to do the transposition, handling this in code is most likely the simplest option. By calling Grid.GetRow/SetRow/etc on your items, you could easily do the transposition.

To avoid putting this into the code behind, you could make an attached property which worked on the grid itself. This would allow you to have the property bind to a boolean or enum in your ViewModel, and perform the transposition at runtime based on business logic.


If you can swap out the Grids for 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>

Then you can make use of this converter

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();
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜