2012-06-19 61 views
4

我有一个包含可变数量控件的包装面板。WPF WrapPanel动态高度

我想要的方向是垂直的(因为对象内将有一个固定的宽度,但高度可变)。

但我遇到的问题是,当滚动条存在时,高度是无限的,所以项目永远不会包裹到第二列。滚动条是必要的,因为经常有更多的对象比可能适合在一个屏幕上。 我可以通过设置固定高度来阻止这种情况,但这不是一个可接受的解决方案,因为每个选择的合理固定高度会有所不同。

基本上我想要一个WrapPanel,它的高度根据面板的宽度和包含的项目数量动态变化。

举例说明:

如果面板的宽​​度足以显示3列,它将:

| 1 5 9 |

| 2 6 - |

| 3 7 - | Height = 4

| 4 8 - |

但是,如果用户改变了窗口,点的大小,它只能容纳2列的高度会增加:

| 1 6 |

| 2 7 |

| 3 8 | Height = 5

| 4 9 |

| 5 - |

而且,我不知道如何可行的,这是但我会像理想的顺序进行项目horizo​​natally但保持方向垂直,所以他​​们会下令:

| 1 2 3 |

| 4 5 6 |

| 7 8 9 |

任何人都可以告诉我如何开始使用这个?我假设它可以通过WrapPanel的自定义实现,但我对如何开始稍有困惑。

感谢,

+0

我不能完全肯定你后什么,但是看看这有助于HTTP://计算器。 com/questions/9769618 /我们怎么设置包装点为包装纸/ 9770590#9770590 – Phil

+0

也许这可以帮助你,'WrapGridPanel':http://stackoverflow.com/questions/ 4598377/WPF的wrappanel与 - 一些项-具有-A-高度的 –

回答

3

Manged达到什么样的,我需要用下面的代码:

public class InvertedWrapPanel : WrapPanel 
{ 
    private int itemsPerRow = 0; 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     if (Orientation == Orientation.Horizontal) 
     { 
      return base.MeasureOverride(availableSize); 
     } 
     else //Orientation is vertical 
     { 
      double w = availableSize.Width; 

      double maxChildWidth = 0; 

      foreach (UIElement child in Children) 
      { 
       //Get the current childs desired size parameters 
       child.Measure(availableSize); 

       //Store off the maximum child width 
       if (child.DesiredSize.Width > maxChildWidth) 
        maxChildWidth = child.DesiredSize.Width; 
      } 

      //See how many items we can fit in a row 
      itemsPerRow = Convert.ToInt32(Math.Floor(w/maxChildWidth)); 

      return base.MeasureOverride(availableSize); 
     } 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     if (Orientation == Orientation.Horizontal) 
     { 
      return base.ArrangeOverride(finalSize); 
     } 
     else //Orientation is vertical 
     { 
      double currentX = 0; 
      double currentY = 0; 

      int col = 0; 

      double lastX = 0; 
      double lastWidth = 0; 

      //Arrays to store differing column heights 
      double[] lastY = new double[itemsPerRow]; 
      double[] lastHeight = new double[itemsPerRow]; 

      double[] colHeights = new double[itemsPerRow]; 

      foreach (UIElement child in Children) 
      { 
       //If we've reached the end of a row 
       if (col >= itemsPerRow) 
       { 
        col = 0; 
        currentX = 0; //reset the x-coordinate for first column 
       } 
       else 
        currentX = lastX + lastWidth; //Increase the x-coordinate 

       //Increase the y-coordinates for the current column 
       currentY = lastY[col] + lastHeight[col]; 

       //Draw the element 
       child.Arrange(new Rect(currentX, currentY, child.DesiredSize.Width, child.DesiredSize.Height)); 

       //Store off the current child's parameters 
       lastX = currentX; 
       lastWidth = child.DesiredSize.Width; 

       lastY[col] = currentY; 
       lastHeight[col] = child.DesiredSize.Height; 

       colHeights[col] += child.DesiredSize.Height; 

       col++; 
      } 

      //Set the height of the panel to the max column height. 
      //Otherwise scroll bar will set height to infinity. 
      double maxHeight = 0; 

      foreach (double d in colHeights) 
      { 
       if (d > maxHeight) 
        maxHeight = d; 
      } 

      base.Height = maxHeight; 

      return finalSize; 
     } 
    }