My name is Edward Tanguay. I'm an American software and web developer living and working in Berlin, Germany.
5 hours ago: If you are a developer in Berlin and need to improve your English, I'm looking for groups to teach after work: http://tanguay.info/itenglish.
6 hours ago: As far as I'm concerned, the singularity is already here, every time I wake up twitter tells me something amazing was created while I slept.
6 hours ago: We're not suffering from information overload, we're suffering from faulty filtering.
6 hours ago: Classic literature for free as nicely formatted 1-page or 2-page PDF downloads: http://www.planetebook.com/free-ebooks.asp.
6 hours ago: Yes, when you pour coffee, "a lightning storm of neuronal activity occurs almost across the entire brain": http://is.gd/eWO1T @pholdings.
23 hours ago: If you put two spaces after a period or use underlining for emphasis, you were born before 1980.
23 hours ago: Word of the day: infovore, n. an animal with a voracious appetite for information.
yesterday: It's said that on average people use less than 10% of their brain, but I think on average computers use less than 1% of their CPU.
2 days ago: Saturday fun: team drawing on two computers with six-year-old in a shared google doc diagram.
2 days ago: Someday I want to produce a developer podcast called "What's that?" but for now "the developer's life" is a nice genre: http://is.gd/eTURO.
3 days ago: Here's a use-case for datapod format, recording human-readable data that later can be used as a datasource: http://is.gd/eSsLg @pholdings.
WPF CODE EXAMPLE created on Thursday, February 25, 2010 permalink
How to convert a tabbed outline text to a XAML TreeView
This example shows how an outline text created with tabs can be converted XAML tree view.
XAML:
<Window x:Class="TestMakeOutline833.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="650">
    <Window.Resources>
        <HierarchicalDataTemplate x:Key="sectionTemplate"
            ItemsSource="{Binding OutlineObjects}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Line}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <StackPanel Margin="10">
        <StackPanel Orientation="Horizontal" Margin="0 0 0 10">

            <ScrollViewer
                Width="300"
                Height="200"
                Margin="0 0 10 0">
                <TextBox
                    x:Name="MainTextBox"
                    AcceptsReturn="True"
                    AcceptsTab="True"

                    Text="{Binding OutlineText}"/>
            </ScrollViewer>

            <TreeView ItemsSource="{Binding OutlineObjects}"
                Width="200"
                Height="200"
                ItemTemplate="{StaticResource sectionTemplate}">
            </TreeView>

        </StackPanel>
        <StackPanel HorizontalAlignment="Left">
            <Button Content="Convert Text to Outline" Click="Button_Click_Convert"/>
        </StackPanel>
    </StackPanel>
</Window>

Code Behind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Documents;
using System.ComponentModel;
using System.Collections.ObjectModel;

namespace TestMakeOutline833
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        #region ViewModelProperty: OutlineText
        private string _outlineText;
        public string OutlineText
        {
            get
            {
                return _outlineText;
            }

            set
            {
                _outlineText = value;
                OnPropertyChanged("OutlineText");
            }
        }
        #endregion //

        #region ViewModelProperty: OutlineObjects
        private ObservableCollection<OutlineObject> _outlineObjects = new ObservableCollection<OutlineObject>();
        public ObservableCollection<OutlineObject> OutlineObjects
        {
            get
            {
                return _outlineObjects;
            }

            set
            {
                _outlineObjects = value;
                OnPropertyChanged("OutlineObjects");
            }
        }
        #endregion //

        public Window1()
        {
            InitializeComponent();
            DataContext = this;

            OutlineText = StringHelpers.GetDefaultTextBlock();
            MainTextBox.Focus();
            BuildOutline();
        }

        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion //

        void Button_Click_Convert(object sender, RoutedEventArgs e)
        {
            BuildOutline();
        }

        void BuildOutline()
        {
            OutlineObjects.Clear();
            OutlineManager om = new OutlineManager(OutlineText);

            foreach (var outlineObject in om.OutlineObjects)
            {
                OutlineObjects.Add(outlineObject);
            }
        }
    }

    public class OutlineManager
    {
        private string outlineBlock;
        private List<string> outlineBlockLines;

        public List<OutlineObject> OutlineObjects { get; set; }

        public OutlineManager(string outlineBlock)
        {
            this.outlineBlock = outlineBlock;
            this.outlineBlockLines = StringHelpers.ConvertBlockToLines(outlineBlock);
            OutlineObjects = new List<OutlineObject>();
            ProcessOutline();
        }

        void ProcessOutline()
        {
            //convert file contents to object collection
            Stack<OutlineObject> parents = new Stack<OutlineObject>();
            int lastLevel = 0;
            foreach (var line in outlineBlockLines)
            {
                OutlineObject oo = new OutlineObject(line);

                if (oo.Level == 0)
                {
                    //root element
                    OutlineObjects.Add(oo);
                    parents.Push(oo);
                    lastLevel = 0;
                }
                else if (oo.Level - lastLevel > 1)
                {
                    //skipped generation(s)
                    throw new Exception("outline structure invalid");
                }
                else if (oo.Level - lastLevel == 1)
                {
                    //child element
                    OutlineObject topObject = parents.Peek();
                    topObject.OutlineObjects.Add(oo);
                    parents.Push(oo);
                    lastLevel++;
                }
                else if (oo.Level == lastLevel)
                {
                    //sibling element
                    parents.Pop();
                    OutlineObject topObject = parents.Peek();
                    topObject.OutlineObjects.Add(oo);
                    parents.Push(oo);
                }
                else if (oo.Level < lastLevel)
                {
                    int levelDifference = lastLevel - oo.Level;
                    for (int i = 0; i < levelDifference + 1; i++)
                    {
                        parents.Pop();
                    }
                    OutlineObject topObject = parents.Peek();
                    topObject.OutlineObjects.Add(oo);
                    parents.Push(oo);
                    lastLevel = oo.Level;
                }
            }
        }

        public static List<OutlineObject> GetOutline(string block)
        {
            OutlineManager om = new OutlineManager(block);
            return om.OutlineObjects;
        }
    }

    public class OutlineObject
    {
        public List<OutlineObject> OutlineObjects { get; set; }
        public string Line { get; set; }
        public int Level { get; set; }

        public OutlineObject(string rawLine)
        {
            OutlineObjects = new List<OutlineObject>();
            Level = rawLine.CountPrecedingDashes();
            Line = rawLine.Trim(new char[] { '-', ' ', 't' });
        }
    }

    public static class StringHelpers
    {
        public static string GetDefaultTextBlock()
        {
            return "countries" + Environment.NewLine +
                "tfrance" + Environment.NewLine +
                "ttparis" + Environment.NewLine +
                "ttbordeaux" + Environment.NewLine +
                "tgermany" + Environment.NewLine +
                "tthamburg" + Environment.NewLine +
                "ttberlin" + Environment.NewLine +
                "tthannover" + Environment.NewLine +
                "ttmunich" + Environment.NewLine +
                "titaly" + Environment.NewLine +
                "subjects" + Environment.NewLine +
                "tmath" + Environment.NewLine +
                "ttalgebra" + Environment.NewLine +
                "ttcalculus" + Environment.NewLine +
                "tscience" + Environment.NewLine +
                "ttchemistry" + Environment.NewLine +
                "ttbiology" + Environment.NewLine +
                "other" + Environment.NewLine +
                "tthis" + Environment.NewLine +
                "tthat";
        }

        public static int CountPrecedingDashes(this string line)
        {
            int tabs = 0;
            StringBuilder sb = new StringBuilder();
            foreach (var c in line)
            {
                if (c == 't')
                    tabs++;
                else
                    break;
            }
            return tabs;
        }

        public static List<string> ConvertBlockToLines(this string block)
        {
            string fixedBlock = block.Replace(Environment.NewLine, "§");
            List<string> lines = fixedBlock.Split('§').ToList<string>();
            lines.ForEach(s => s = s.Trim());
            lines.TrimBlankLines();

            return lines;
        }

        public static void TrimBlankLines(this List<string> list)
        {
            while (0 != list.Count && string.IsNullOrEmpty(list[0]))
            {
                list.RemoveAt(0);
            }
            while (0 != list.Count && string.IsNullOrEmpty(list[list.Count - 1]))
            {
                list.RemoveAt(list.Count - 1);
            }
        }
    }
}
need markup?