2011-01-19 72 views
1

我想寫一個自定義Panel,可以使用裝飾器模板。這意味着它將有一些其他Panel作爲屬性。當一些元素被添加到我的自定義面板中時,我想將其也添加到裝飾面板(存儲在屬性中),並且當某些元素被刪除時,我也想從裝飾面板中刪除它。我怎麼做 ?如何裝飾WPF面板?

是否有某種方法被重寫或某些事件在更改爲InternalCholdrens時觸發?

謝謝

編輯:Basicly我想要做的事就像this我想任何面板轉向動畫之一。所以我想用我的裝飾器來裝飾任何面板,使它變成動畫。

+0

你期望能夠用「任何面板」做什麼樣的動畫?不同類型的面板(網格,畫布,堆棧面板,dockpanel等)對於如何在其中定位項目具有完全不同的功能。我沒有看到有一種通用的方式來做你所描述的...... – 2011-01-19 20:53:51

+0

有。但那是我的知識,而且描述它並不容易。但技術細節似乎對我來說是一個問題:( – drasto 2011-01-19 21:12:14

回答

2

你不能做到這一點,很遺憾。

你會立即得到的是一個例外,說一個控件只能有一個邏輯父項。

雖然你可以做的是做雙重授權。你的小組委託測量/安排到另一個小組,並作爲回報,它提供了'鬼',它將作爲一個孩子,並將他們自己的措施/安排委託給你的小組的孩子。

下面的代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows.Controls; 
using System.Windows; 

public class DelegatePanel : Panel 
{ 
    private sealed class DelegateChild : FrameworkElement 
    { 
     readonly Func<Size, Size> measure; 
     readonly Func<Size, Size> arrange; 

     public DelegateChild(Func<Size,Size> measure, Func<Size,Size> arrange) 
     { 
      this.measure = measure; 
      this.arrange = arrange; 
     } 

     protected override Size MeasureOverride(Size availableSize) 
     { 
      return measure(availableSize); 
     } 

     protected override Size ArrangeOverride(Size finalSize) 
     { 
      return arrange(finalSize); 
     } 
    } 

    readonly Dictionary<UIElement, UIElement> delegateByChild = new Dictionary<UIElement,UIElement>(); 

    public Panel LayoutPanel 
    { 
     get { return (Panel)GetValue(LayoutPanelProperty); } 
     set { SetValue(LayoutPanelProperty, value); } 
    } 

    public static readonly DependencyProperty LayoutPanelProperty = 
     DependencyProperty.Register("LayoutPanel", typeof(Panel), typeof(DelegatePanel), new PropertyMetadata(null)); 

    protected override Size MeasureOverride(Size availableSize) 
    { 
     if(this.LayoutPanel==null) 
      return base.MeasureOverride(availableSize); 

     this.delegateByChild.Clear(); 

     this.LayoutPanel.Children.Clear(); 
     foreach (UIElement _child in this.Children) 
     { 
      var child = _child; 

      var delegateChild = new DelegateChild(
        availableChildSize => 
        { 
         child.Measure(availableChildSize); 
         return child.DesiredSize; 
        }, 
        finalChildSize => 
        { 
         return finalChildSize; 
        }); 

      delegateByChild[child] = delegateChild; 

      this.LayoutPanel.Children.Add(delegateChild); 
     } 

     this.LayoutPanel.Measure(availableSize); 
     return this.LayoutPanel.DesiredSize; 
    } 

    protected override Size ArrangeOverride(Size finalSize) 
    { 
     if(this.LayoutPanel==null) 
      return base.ArrangeOverride(finalSize); 

     this.LayoutPanel.Arrange(new Rect(finalSize)); 

     foreach (var kv in delegateByChild) 
     { 
      var child = kv.Key; 
      var delegateChild = kv.Value; 

      var position = delegateChild.TranslatePoint(default(Point), this.LayoutPanel); 

      Rect finalChildBounds = new Rect(
       position, 
       delegateChild.RenderSize); 

      child.Arrange(finalChildBounds); 
     } 

     return this.LayoutPanel.RenderSize; 
    } 
} 

聲明:此沒有實現VirtualizingPanel。因此,雖然它在ItemsControl和該團伙內部工作 - 但對於大型館藏來說,其執行速度不夠快。