Click here to Skip to main content
15,886,026 members
Articles / Desktop Programming / WPF

WPF Breadcrumb Folder TextBox

Rate me:
Please Sign up or sign in to vote.
4.41/5 (10 votes)
15 Jan 2009LGPL36 min read 100.8K   1.7K   71  
This article provides an implementation of a WPF Breadcrumb control, and describes how to develop one.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
using System.Diagnostics;

namespace QuickZip.UserControls.Breadcrumb.Tools
{
    public class BreacrumbCorePanel : Panel
    {
        private static DependencyProperty IsArrangedProperty = DependencyProperty.RegisterAttached("IsArranged", typeof(bool), 
            typeof(BreacrumbCorePanel), new PropertyMetadata(false));
        private static DependencyProperty ArrangedRectProperty = DependencyProperty.RegisterAttached("ArrangedRect", typeof(Rect),
            typeof(BreacrumbCorePanel), new PropertyMetadata(new Rect(0, 0, 0, 0)));

        private Size lastfinalSize;

        protected override Size MeasureOverride(Size availableSize)
        {
            Size resultSize = new Size(0, 0);

            foreach (UIElement child in Children)
            {
                //Fix:This is a temp fix for ArithException when loading icons for Mds files.
                try { child.Measure(availableSize); }
                catch { }
                resultSize.Width += child.DesiredSize.Width;
                resultSize.Height = Math.Max(resultSize.Height, child.DesiredSize.Height);
            }

            resultSize.Width =
                double.IsPositiveInfinity(availableSize.Width) ?
                resultSize.Width : availableSize.Width;
            resultSize.Width = Math.Min(resultSize.Width, availableSize.Width);

            return resultSize;
        }

        #region AttachedProperties
        private bool GetIsArranged(UIElement element)
        {
            return (bool)element.GetValue(IsArrangedProperty);
        }

        public void SetIsArranged(UIElement element, bool value)
        {
            element.SetValue(IsArrangedProperty, value);
        }

        private Rect GetArrangedRect(UIElement element)
        {
            return (Rect)element.GetValue(ArrangedRectProperty);
        }

        public void SetArrangedRect(UIElement element, Rect value)
        {
            element.SetValue(ArrangedRectProperty, value);
        }
        #endregion

        private List<UIElement> GhostFolders = new List<UIElement>();

        protected override Size ArrangeOverride(Size finalSize)
        {
            foreach (UIElement g in GhostFolders)  //03-01-09 : Dirty Ghost Folder Fix.
                g.IsHitTestVisible = true;
            GhostFolders.Clear();

            if (Children.Count > 0) //05-01-09 : Remember Child position
            {
                UIElement lastChild = Children[Children.Count-1];                
                if (GetIsArranged(lastChild) && lastfinalSize == finalSize)
                {
                    for (int i = 0; i < Children.Count; i++ )
                        if (GetIsArranged(Children[i]))
                            Children[i].Arrange(GetArrangedRect(Children[i]));
                        else
                        {
                            Children[i].IsHitTestVisible = false;
                            GhostFolders.Add(Children[i]);
                        }

                        return finalSize; //No arrange necessary
                }
            }

            lastfinalSize = finalSize;

            if (this.Children == null || this.Children.Count == 0)
                return finalSize;

            double finalWidth = finalSize.Width - 30;
            double totalX = 0;

            for (int i = Children.Count - 1; i >= 0; i--)
                Children[i].Measure(finalSize);

            for (int i = Children.Count - 1; i >= 0; i--)
                if (totalX + Children[i].DesiredSize.Width <= finalWidth || i == Children.Count - 1)
                {
                    totalX += Children[i].DesiredSize.Width;
                }
                else break;
            
            double curX = Math.Min(totalX, finalWidth) + 1;            
            
            for (int i = Children.Count - 1; i >= 0; i--)
            {
                UIElement child = Children[i];
                if (curX >= child.DesiredSize.Width || i == Children.Count -1)
                {                    
                    if (curX < child.DesiredSize.Width)
                        SetArrangedRect(child, new Rect(0, 0, curX, child.DesiredSize.Height));
                    else
                    SetArrangedRect(child, new Rect(curX - child.DesiredSize.Width, 0, child.DesiredSize.Width, finalSize.Height));
                    SetIsArranged(child, true);
                    child.IsHitTestVisible = true;
                }
                else
                {                    
                    for (int j = 0; j <= Math.Min(i, Children.Count -1); j++)
                    {
                        child = Children[j];
                        SetArrangedRect(child, new Rect(0, 0, 0, 0));
                        child.Arrange(GetArrangedRect(child));
                        SetIsArranged(child, false);                       
                        GhostFolders.Add(child);
                        child.IsHitTestVisible = false;
                    }
                    break;
                }                        

                child.Arrange(GetArrangedRect(child));
                curX -= child.DesiredSize.Width;
            }

            return finalSize;
        }
    }
}

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 GNU Lesser General Public License (LGPLv3)


Written By
Founder
Hong Kong Hong Kong

Comments and Discussions