2011-04-07 66 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