Comment : remplacer l'arborescence logique

Bien que cela ne soit pas nécessaire dans la plupart des cas, les auteurs de contrôle avancés peuvent remplacer l'arborescence logique.

Exemple

Cet exemple explique comment sous-classer StackPanel pour remplacer l'arborescence logique (dans ce cas, pour appliquer un comportement que seul le panneau peut avoir et qui restitue un seul élément enfant). Ce comportement, qui n'est pas nécessairement souhaitable, est repris dans cet exemple afin d'illustrer le scénario permettant de remplacer l'arborescence logique normale d'un élément.

    Public Class SingletonPanel
        Inherits StackPanel
        'Private _children As UIElementCollection 
        Private _child As FrameworkElement

        Public Sub New()

        End Sub

        Public Property SingleChild() As FrameworkElement

            Get
                Return _child
            End Get
            Set(ByVal value As FrameworkElement)
                If value Is Nothing Then
                     RemoveLogicalChild(_child)
                Else
                     If _child Is Nothing Then
                         _child = value
                     Else
                         ' raise an exception?
                         MessageBox.Show("Needs to be a single element")
                     End If
                End If
            End Set
        End Property
        Public Sub SetSingleChild(ByVal child As Object)
            Me.AddLogicalChild(child)
        End Sub

        Public Shadows Sub AddLogicalChild(ByVal child As Object)
            _child = CType(child, FrameworkElement)
            If Me.Children.Count = 1 Then
                Me.RemoveLogicalChild(Me.Children(0))
                Me.Children.Add(CType(child, UIElement))
            Else
                Me.Children.Add(CType(child, UIElement))
            End If
        End Sub

        Public Shadows Sub RemoveLogicalChild(ByVal child As Object)

            _child = Nothing
            Me.Children.Clear()
        End Sub
        Protected Overrides ReadOnly Property LogicalChildren() As IEnumerator
           Get
           ' cheat, make a list with one member and return the enumerator
           Dim _list As New ArrayList()
           _list.Add(_child)
           Return CType(_list.GetEnumerator(), IEnumerator)
           End Get
        End Property
    End Class
public class SingletonPanel : StackPanel
{
    //private UIElementCollection _children; 
    private FrameworkElement _child;

    public SingletonPanel() {

    }

    public FrameworkElement SingleChild
    {

        get { return _child;}
        set
        {
            if (value==null) {
                 RemoveLogicalChild(_child);
            } else {             
                 if (_child==null) {
                     _child = value;
                 } else {
                     // raise an exception?
                     MessageBox.Show("Needs to be a single element");
                 }
            }
        } 
    }
    public void SetSingleChild(object child)
    {
        this.AddLogicalChild(child);
    }

    public new void AddLogicalChild(object child)
    {
        _child = (FrameworkElement)child;
        if (this.Children.Count == 1)
        {
            this.RemoveLogicalChild(this.Children[0]);
            this.Children.Add((UIElement)child);
        }
        else
        {
            this.Children.Add((UIElement)child);
        }
    }

    public new void RemoveLogicalChild(object child)

    {
        _child = null;
        this.Children.Clear();
    }
    protected override IEnumerator LogicalChildren
    {
       get {
       // cheat, make a list with one member and return the enumerator
       ArrayList _list = new ArrayList();
       _list.Add(_child);
       return (IEnumerator) _list.GetEnumerator();}
    }
}

Pour plus d'informations sur l'arborescence logique, consultez Arborescences dans WPF.