/// <summary>
        /// Find the given category in the tree and return the 'path' of parent objects that get us to that category.
        /// </summary>
        private bool FindTreeItemByCategory(ItemCollection itemCollection, Category value, List <object> path)
        {
            foreach (object item in itemCollection)
            {
                CategoryGroup g = item as CategoryGroup;
                if (g != null)
                {
                    path.Add(g);
                    if (FindTreeItemByCategory(g.Subcategories, value, path))
                    {
                        return(true);
                    }
                    path.Remove(g);
                }
                else
                {
                    Category c = item as Category;
                    path.Add(c);
                    if (c == value)
                    {
                        return(true);
                    }

                    if (c.Subcategories != null && c.Subcategories.Count > 0)
                    {
                        if (FindTreeItemByCategory(c.Subcategories, value, path))
                        {
                            return(true);
                        }
                    }
                    path.Remove(c);
                }
            }
            return(false);
        }
        void OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs <object> e)
        {
            Category dataBoundItemTreeview = (this.treeView.SelectedItem as Category);

            if (dataBoundItemTreeview != null)
            {
                if (SelectionChanged != null)
                {
                    SelectionChanged(this, EventArgs.Empty);
                }
            }
            CategoryGroup group = (this.treeView.SelectedItem as CategoryGroup);

            if (group != null)
            {
                if (GroupSelectionChanged != null)
                {
                    GroupSelectionChanged(this, EventArgs.Empty);
                }
            }
        }
        void UpdateRoots()
        {
            if (insideUpdateRoots)
            {
                return;
            }
            insideUpdateRoots = true;

            try
            {
                bool hasRoots = this.treeView.ItemsSource != null;
                ObservableCollection <CategoryGroup> groups = new ObservableCollection <CategoryGroup>();

                List <Category> roots;

                if (string.IsNullOrWhiteSpace(filterCategory))
                {
                    // No filter return the top root items as is
                    roots = this.money.Categories.GetRootCategories();
                }
                else
                {
                    roots = GetDeepFilteredRootCategories();
                }

                //--------------------------------------------------------------
                // Create the 4 top holding Groups
                //
                //      0 - INCOME
                //      1 - EXPENSE
                //      2 - NONE
                //      3 - TOTAL
                //

                decimal balance = 0;

                foreach (CategoryType t in new CategoryType[] { CategoryType.Income, CategoryType.Expense, CategoryType.Investments, CategoryType.None })
                {
                    ObservableCollection <Category> list = new ObservableCollection <Category>();

                    foreach (Category c in roots)
                    {
                        if (c == this.MyMoney.Categories.Split)
                        {
                            continue;
                        }

                        if (c.Type == t || (c.Type == CategoryType.Savings && t == CategoryType.Income))
                        {
                            balance += c.Balance;
                            list.Add(c);
                        }
                    }
                    CategoryGroup g = new CategoryGroup()
                    {
                        Name          = t.ToString(),
                        Subcategories = list
                    };

                    groups.Add(g);
                }

                total = new CategoryBalance()
                {
                    Name = "Total", Balance = balance
                };
                groups.Add(total);

                if (!hasRoots)
                {
                    this.treeView.ItemsSource = groups;
                }
                else
                {
                    // merge!
                    ObservableCollection <CategoryGroup> oldGroups = this.treeView.ItemsSource as ObservableCollection <CategoryGroup>;

                    Debug.Assert(oldGroups.Count == groups.Count);

                    for (int i = 0; i < groups.Count; i++)
                    {
                        CategoryGroup a = groups[i];
                        CategoryGroup b = oldGroups[i];
                        if (a is CategoryBalance)
                        {
                            CategoryBalance ab = (CategoryBalance)a;
                            CategoryBalance bb = (CategoryBalance)b;
                            bb.Balance = ab.Balance;
                        }
                        else
                        {
                            SyncCollections(a.Subcategories, b.Subcategories);
                        }
                    }
                }
            }
            finally
            {
                insideUpdateRoots = false;
            }
        }