我想编写一个可以使用Decorator patern的自定义Panel
。这意味着它将有一些其他Panel
作为属性。当一些元素添加到我的自定义面板时,我想将它也添加到装饰面板(存储在属性中),当一些元素被删除时,我也想从装饰面板中删除它。我该怎么做?
当更改为InternalCholdrens时,是否有某些方法需要覆盖或触发某些事件?
谢谢
编辑:基本上我想做this之类的事我想把任何面板变成动画面板。所以我想用我的装饰器装饰任何面板,以便它变得动画。
答案 0 :(得分: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和团队中工作,但它对于大型集合来说效率不高。
答案 1 :(得分:1)
我不完全理解这个问题的上下文,但你可以覆盖OnVisualChildrenChanged
http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.onvisualchildrenchanged.aspx