Как украсить панель WPF? - PullRequest
       25

Как украсить панель WPF?

1 голос
/ 19 января 2011

Я хочу написать пользовательский Panel, в котором будет использоваться шаблон Decorator. Это означает, что у него будет некоторое другое Panel как свойство. Когда какой-то элемент добавляется в мою пользовательскую панель, я хочу добавить его также в декорированную панель (сохраненную в свойстве), а когда какой-то элемент удаляется, я хочу удалить его и из декорированной панели. Как мне это сделать?

Есть ли какой-нибудь метод, который нужно переопределить, или какое-то событие вызывается, когда происходит изменение на InternalCholdrens?

Спасибо

РЕДАКТИРОВАТЬ: В основном я хочу сделать что-то вроде this Я хочу превратить любую панель в анимированную. Поэтому я хочу украсить любую панель моим декоратором, чтобы она стала анимированной.

Ответы [ 2 ]

2 голосов
/ 20 января 2011

К сожалению, вы не можете этого сделать.

То, что вы получите немедленно, - исключение, говорящее, что у элемента управления может быть только один логический родитель.

Хотя вы можете сделать этодвойная делегация.Делегаты вашей панели измеряют / организуют другую панель, а взамен она предоставляет ей «призраков», которые будут действовать как дети и делегировать свои собственные меры / аранжировки детям вашей панели.

Вот код:

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 голос
/ 19 января 2011

Я не совсем понимаю контекст этого вопроса, но вы можете переопределить OnVisualChildrenChanged

http://msdn.microsoft.com/en-us/library/system.windows.controls.panel.onvisualchildrenchanged.aspx

...