I want to write a custom Panel
that would make use of Decorator patern. That means it will have some other Panel
as a property. When some element is added to my custom panel I want to add it also to decorated panel (stored in property) and when some e开发者_StackOverflowlement is removed, I want to remove it from decorated panel as well. How do I do that ?
Is there some method that is to be overriden or some event is fired when change to InternalCholdrens happen ?
Thank you
EDIT: Basicly I want to do something like this I want to turn any panel to the animated one. So I want to decorate any panel with my decorator so it becomes animated.
You can't do that, unfortunately.
What you will get immediately is an exception saying a control can have only one logical parent.
Although what you can do is to do double-delegation. Your panel delegates measure/arrange to another panel, and in return it provides it with 'ghosts' which will act as a children to it and delegate their own measure/arrange to your panel's children.
Here's the code:
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;
}
}
Disclaimer: this doesn't implement VirtualizingPanel. So whilst it does work inside ItemsControl and the gang -- it won't perform quick enough for large collections.
i don't totally understand the context for this question but you can override OnVisualChildrenChanged
http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.onvisualchildrenchanged.aspx
精彩评论