2011-04-07 120 views
1

我有一个WPF自定义面板,它按照我的要求安排其子元素为螺旋形状。我遇到的问题是在窗口大小调整时缩放这些项目 - 目前它不能缩放。谁能提供解决方案?谢谢 - 奔WPF自定义面板缩放到适合窗口

自定义面板

public class TagPanel : Panel 
{ 
    protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize) 
    { 
     Size resultSize = new Size(0, 0); 

     foreach (UIElement child in Children) 
     { 
      child.Measure(availableSize); 

      resultSize.Width = Math.Max(resultSize.Width, child.DesiredSize.Width); 
      resultSize.Height = Math.Max(resultSize.Height, child.DesiredSize.Height); 

     } 

     resultSize.Width = double.IsPositiveInfinity(availableSize.Width) ? 
      resultSize.Width : availableSize.Width; 

     resultSize.Height = double.IsPositiveInfinity(availableSize.Height) ? 
      resultSize.Height : availableSize.Height; 

     return resultSize; 

    } 

    protected class InnerPos 
    { 
     public UIElement Element { get; set; } 
     public Size Size { get; set; } 
    } 

    private Point GetSpiralPosition(double theta, Size windowSize) 
    { 
     double a = 5.0; 
     double n = 1.0; 

     double r = a * (Math.Pow(theta, 1.0/n)); 

     double x = r * Math.Cos(theta); 
     double y = r * Math.Sin(theta); 

     x += windowSize.Width/2.0; 
     y += windowSize.Height/2.0; 

     return new Point(x,y); 

    } 

    private Rect CreateRectangleCenteredAtPoint(Point pt, double width, double height) 
    { 
     return new Rect(new Point(pt.X - (width/2.0), pt.Y - (height/2.0)), 
      new Size(width, height)); 

    } 

    protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize) 
    { 
     //double startPos = 0.0; 

     List<InnerPos> positions = new List<InnerPos>(); 

     foreach (UIElement ch in Children) 
     { 
      // If this is the first time 
      // we've seen this child, add our transforms 

      //if (ch.RenderTransform as TransformGroup == null) 
      //{ 
      // ch.RenderTransformOrigin = new Point(0, 0.5); 
      // TransformGroup group = new TransformGroup(); 
      // ch.RenderTransform = group; 
      // group.Children.Add(new ScaleTransform()); 
      // group.Children.Add(new TranslateTransform()); 

      //} 

      positions.Add(new InnerPos() 
      { 
       Element = ch, 
       Size = ch.DesiredSize 

      }); 
     } 

     //double currentTopMax 
     List<Rect> alreadyUsedPositions = new List<Rect>(); 

     foreach (InnerPos child in positions.OrderByDescending(i => i.Size.Width)) 
     { 

      for (double theta = 0.0; theta < 100.0; theta += 0.1) 
      { 
       Point spiralPos = GetSpiralPosition(theta, finalSize); 
       Rect centeredRect = CreateRectangleCenteredAtPoint(spiralPos, 
        child.Element.DesiredSize.Width, 
        child.Element.DesiredSize.Height); 

       bool posIsOk = true; 
       foreach (Rect existing in alreadyUsedPositions) 
       { 
        bool positionClashes = existing.IntersectsWith(centeredRect); 
        if (positionClashes == true) 
        { 
         posIsOk = false; 
         break; 
        } 
       } 

       if (posIsOk) 
       { 
        alreadyUsedPositions.Add(centeredRect); 

        child.Element.Arrange(centeredRect); 
        break; 
       } 


      } 

     } 

     return finalSize; 

    } 
} 

回答

0

是在HorizontalAlignmentPanel一套VerticalAlignmentStretchWidth/Height为自动(double.NaN)?

看起来您正在将finalSize传递到GetSpiralPosition(),这是所有真实工作都发生的功能。没有看到这个函数的代码很难说更多,但我认为你正在计算finalSize

您是否调试过当窗口被调整大小时是否使用更新的大小调用Arrange?将有两种方法来测试它:首先,放置一个跟踪点而不是一个断点。将finalSize转储到输出窗口,并在窗口调整大小时查看它是否更改。其次,在窗口中添加一个处理程序到SizeChanged。在处理程序中放置一个断点。当命中断点时,在自定义面板的排列方法中放置一个断点,然后运行。

+0

嗨乔希,感谢您的回复 - 请参阅更新的代码,以便您可以获得更清晰的图像。谢谢 – Ben 2011-04-07 14:06:24

+0

问题是当窗口调整大小时,安排不会被调用新的大小,您可以协助吗? – Ben 2011-04-07 16:15:50

+0

@Ben:你有没有检查Horizo​​ntalAlignment/VerticalAlignment和Width/Height是否设置为我所提到的?如果您观察一个Grid面板,当窗口调整大小时,它会重新排列它的内容。 – 2011-04-07 19:33:05