Click here to Skip to main content
15,895,667 members
Articles / Desktop Programming / WPF

Building a Docking Window Management Solution in WPF

Rate me:
Please Sign up or sign in to vote.
4.28/5 (25 votes)
1 Jan 2011CPOL8 min read 190.3K   15.7K   83  
A docking window solution using WPF as part of Synergy toolkit
///
/// Copyright(C) MixModes Inc. 2010
/// 

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using MixModes.Synergy.VisualFramework.Extensions;
using System.Collections.Generic;

namespace MixModes.Synergy.VisualFramework.Adorners
{
    /// <summary>
    /// Content adorner base class that can be populated with any visual 
    /// </summary>
    internal abstract class ContentAdornerBase : AdornerBase
    {
        /// <summary>
        /// Initializes an Adorner
        /// </summary>
        /// <param name="adornedElement">The element to bind the adorner to</param>
        /// <exception cref="ArgumentNullException">adornedElement is null</exception>
        internal ContentAdornerBase(UIElement adornedElement, FrameworkElement content)
            : base(adornedElement)
        {
            _contentControl = new ContentControl();
            _contentControl.Content = content;
            _contentControl.ApplyTemplate();
            _visualChildren.Add(_contentControl);
        }

        /// <summary>
        /// Finds content with specified name
        /// </summary>
        /// <param name="name">Name of the element to find</param>
        /// <returns>An element with matching name if one exists; null otherwise</returns>
        protected T FindElement<T>(string name) where T:FrameworkElement
        {
            ContentPresenter contentPresenter = VisualTreeHelper.GetChild(_contentControl, 0) as ContentPresenter;
            FrameworkElement content = null;

            if ((contentPresenter == null) || 
                ((content = contentPresenter.Content as FrameworkElement) == null) ||
                (name == null))
            {
                return null;
            }

            Stack<FrameworkElement> searchStack = new Stack<FrameworkElement>();
            searchStack.Push(content);

            while (searchStack.Count > 0)
            {
                FrameworkElement element = searchStack.Pop();

                if (name.Equals(element.Tag))
                {
                    return element as T;
                }

                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
                {
                    FrameworkElement childElement = VisualTreeHelper.GetChild(element, i) as FrameworkElement;

                    if (childElement != null)
                    {
                        searchStack.Push(childElement);
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// When overridden in a derived class, positions child elements and 
        /// determines a size for a <see cref="T:System.Windows.FrameworkElement"/> derived class.
        /// </summary>
        /// <param name="finalSize">The final area within the parent that this element 
        /// should use to arrange itself and its children.</param>
        /// <returns>The actual size used.</returns>
        protected override Size ArrangeOverride(Size finalSize)
        {            
            (AdornedElement as FrameworkElement).EnforceSize();

            _contentControl.Arrange(new Rect(0, 0, DesiredSize.Width, DesiredSize.Height));

            return finalSize;
        }

        // Private members
        private readonly ContentControl _contentControl;
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) MixModes Inc. | Research In Motion
Canada Canada
Ashish worked for Microsoft for a number of years in Microsoft Visual Studio (Architect edition) and Windows Live division as a developer. Before that he was a developer consultant mainly involved in distributed service development / architecture. His main interests are distributed software architecture, patterns and practices and mobile device development.

Currently Ashish serves as a Technical Lead at RIM leading next generation BlackBerry media experience and also runs his own company MixModes Inc. specializing in .NET / WPF / Silverlight technologies. You can visit MixModes at http://mixmodes.com or follow it on Twitter @MixModes

In his free time he is an avid painter, hockey player and enjoys travelling. His blog is at: http://ashishkaila.serveblog.net

Comments and Discussions