在包装面板中水平对齐子元素

时间:2015-08-11 19:40:24

标签: c# wpf

我的窗口中有以下XAML:

<WrapPanel>
    <WrapPanel.Resources>
        <Style TargetType="Rectangle">
            <Setter Property="Margin" Value="10,10,10,10"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
        </Style>
    </WrapPanel.Resources>
    <Rectangle Height="100" Width="100" Fill="Red"/>
    <Rectangle Height="200" Width="200" Fill="Yellow"/>
    <Rectangle Height="150" Width="150" Fill="Green"/>
    <Rectangle Height="50" Width="50" Fill="Blue"/>
    <Rectangle Height="250" Width="250" Fill="Purple"/>
</WrapPanel>

在设计器中生成以下UI: Current layout

我正在寻找的是一种水平对齐的方法。包装面板中的子元素,以便窗口看起来像这样: Desired layout

有没有办法在包装面板中实现这一点,还是我需要考虑使用其他控件或编写自定义控件?

此图片还说明了我想要实现的目标: enter image description here

2 个答案:

答案 0 :(得分:1)

看起来你想要的是一个包含行和列的网格。

<Grid>
    <Grid.Resources>
        <Style TargetType="Rectangle">
            <Setter Property="Margin" Value="10,10,10,10"/>
            <Setter Property="VerticalAlignment" Value="Top"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
    </Grid.Resources>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
        <ColumnDefinition Width="Auto"/>
    </Grid.ColumnDefinitions>
    <Rectangle Height="100" Width="100" Fill="Red" Grid.Column="0"/>
    <Rectangle Height="200" Width="200" Fill="Yellow" Grid.Column="1"/>
    <Rectangle Height="150" Width="150" Fill="Green"  Grid.Column="2"/>
    <Rectangle Height="50" Width="50" Fill="Blue"  Grid.Column="3"/>
    <Rectangle Height="250" Width="250" Fill="Purple" Grid.Row="1"/>
</Grid>

这可以实现第二张图片的精确布局,但不会随着窗口大小的变化而换行。要做到这一点,您可能需要一个自定义Grid控件,可以在调整容器大小时动态排列子项。

答案 1 :(得分:1)

使用一些不同的技术,您可以到达您想要的位置。这个SO answer显示了如何定义响应列宽:

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

如果这还不够,你可以走自己的路径,拥有一个使用网格布局的自定义控件,并重新定位每个子控件当前所在的列/行,以及控件或窗口调整大小事件,重做基于列/像素计算的布局定位。

<强>更新

对于自定义控件,您可以尝试类似于此的内容:

public class CustomLayout:Control    {       私人列表儿童;

  public CustomLayout()
  {
      children = new List<Control>();      
  }

  public void AddChild(Control childToAdd)
  {
      children.Add(childToAdd);
      // TODO: Determine if new layout is needed.
  }

  public void RemoveChild(Control childToRemove)
  {
      children.Remove(childToRemove);
      // TODO: Determine if new layout is needed.
  }

  // Call to update the layout.
  private void PerformLayout(int columns, int rows)
  {
     Grid layoutGrid = new Grid();
     // TODO: Programmatically build grid layout.
     RowDefinition row = new RowDefinition();
     row.Height = 100;
     layoutGrid.Rows.Add(row);

     // Methods for layout:
     // Grid.SetRow(rowID, childControl);
     // Grid.SetColumn(columnID, childControl);


     // Note: This may produce some flashing on resize, so there may be better ways to remove/add the grid such as redoing rows and columns instead.
     Controls.Clear();
     Controls.Add(layoutGrid);
  }

  // Should be called when the window or parent resizes. I can't remember the events in question.
  public void OnResize()
  {
     int columns;
     int rows;
     // TODO: Calculate columns/rows
     PerformLayout(columns, rows);
  }

}

希望这能让你朝着正确的方向前进。请记住,这是伪代码,可能无法完全编译。