2011-01-19 5 views
1

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

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

Спасибо

EDIT: Основном я хочу сделать что-то вроде this я хочу, чтобы превратить любую панель анимационного один. Поэтому я хочу украсить любую панель своим декоратором, чтобы она стала анимированной.

+0

Какую анимацию вы ожидаете от «любой панели»? различные типы панелей (сетка, холст, стековая панель, док-панель и т. д.) имеют совершенно разные возможности для того, как они позиционируют элементы внутри них. я не вижу, что существует общий способ делать то, что вы описываете ... –

+0

Существует. Но это мое знаю, и это непросто описать. Но технические детали, кажется, являются проблемой для меня :( – drasto

ответ

1

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

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

+0

Я думал так же, но это правильная практика? Является ли OnVisualChildrenChanged также вызванным, когда элемент добавляется из-за привязки? Это было бы желательно. это OnVisualChildrenChanged изменилось при добавлении границы? Это нежелательно ... – drasto

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 и банды, он не будет достаточно быстро выполнять большие коллекции.

+0

Когда я впервые взглянул на «двойное делегирование», я был уверен, что вы сказали * Хотя вы можете сделать это, чтобы играть [Double Dragon] (http: //en.wikipedia.org/wiki/Double_Dragon).* С этим я полностью согласен. :) –

+0

Обратите внимание, что такие вещи, как DockPanel.Dock, не будут распространяться от ваших реальных детей до детей-призраков для делегированной панели макета. –

Смежные вопросы