【问题标题】:Horizontally aligning child elements in a wrap panel在环绕面板中水平对齐子元素
【发布时间】:2015-08-12 04:32:56
【问题描述】:

我的窗口中有以下 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:

我正在寻找的是一种在换行面板中“水平对齐”子元素的方法,以便窗口看起来像这样:

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

这张图片还说明了我想要实现的目标:

【问题讨论】:

  • 您能否详细说明所需布局的约束条件?红色矩形似乎不像其他矩形那样“水平对齐”,所以并不完全清楚你在追求什么。要获得您为黄色矩形提供边距的图像就足够了,但我猜您需要一些不那么手工制作的东西。
  • 我只是在为数据输入屏幕测试一些东西,我试图在表格中对齐每个“组”控件,例如布局,而不是让每个控件交错。在我的实际应用程序中,我将用堆栈面板/网格替换矩形。矩形仅用于演示。
  • 是的,我对矩形没有任何问题。我不明白为什么红色矩形与紫色矩形水平重叠,但黄色矩形向右移动?是不是每行(这里:红色和紫色)​​的第一个元素是左对齐的,后面的元素(这里:黄色和无)不允许水平重叠?
  • 我添加的第三张图片有帮助吗?我基本上是在寻找行为类似于网格控件的东西,而无需明确指定我需要的行数或列数。
  • 是的,谢谢,现在很清楚了:-)

标签: c# wpf


【解决方案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>

如果这还不够,您可以继续使用自定义控件,该控件使用网格布局并重新定位每个子控件当前所在的列/行,并在控件或窗口调整大小事件中重做基于列/像素计算的布局定位。

更新:

对于自定义控件,您可以尝试类似这样的操作:

公共类 CustomLayout : 控制 { 私有列表子项;

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

}

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

【讨论】:

  • 我认为在这种情况下可能需要自定义控件。
  • 它会给你最大的控制权,但也需要一些时间来获得正确的实施。
  • 关于 SO 是否有任何问题可以解释如何使用我需要的行为进行控制?
  • 我会尝试在我的答案中为您发布伪代码更新,以帮助您入门。
  • 太好了。稍后我会看看这个。
【解决方案2】:

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

<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 控件,该控件在调整容器大小时动态排列子项。

【讨论】:

  • 这是我过去考虑的,但我需要的是可以在窗口改变大小时调整大小的东西。使用网格(和统一网格),我知道您已经提前指定了行和列。我需要一些不需要明确声明我需要多少行/列的东西。我唯一能描述的词就是布局需要“响应式”。
  • 我猜你需要创建一个自定义面板控件,它会在内部使用 Grid 作为子元素。实现起来会非常棘手。
  • 不是我真正想做的,但如果是这样,那就这样吧。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-27
  • 1970-01-01
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多