private bool findItemAndRemoveRecursively(IList<TreeItem> items, TreeItem item) {
     if (items.Contains(item)) {
         items.Remove(item);
         return true;
     }
     foreach (TreeItem treeItem in items) {
         if (findItemAndRemoveRecursively(treeItem.Items, item)) return true;
     }
     return false;
 }
 private void expandCollapse( TreeItem item ) {
     int index = treeItemsFlat.IndexOf(item);
     if ( item.Expanded ) {
         collapse(item);
         item.expanded = false;
         // Need to update item string (because Expanded status has been changed)
         listBox.Items[index] = item.DisplayTitle;
     } else {
         expand(item);
         item.expanded = true;
         // Need to update item string (because Expanded status has been changed)
         listBox.Items[index] = item.DisplayTitle;
     }
 }
        private void collapse(TreeItem item) {
            // Children are collapsed but with Expanded state saved
            foreach (TreeItem child in item.Items.Where(child => child.Expanded)) {
                collapse(child);
            }

            int index = treeItemsFlat.IndexOf(item);
            foreach (TreeItem child in item.Items) {
                treeItemsFlat.RemoveAt(index + 1);
                if (child.Disabled) listBox.DisabledItemsIndexes.Remove(index + 1);
                listBox.Items.RemoveAt(index + 1);
                child.Position = -1;
            }
            for (int k = index + 1; k < treeItemsFlat.Count; k++) {
                treeItemsFlat[k].Position -= item.Items.Count;
            }
        }
        private void expand(TreeItem item) {
            int index = treeItemsFlat.IndexOf(item);
            for (int i = 0; i < item.Items.Count; i++) {
                TreeItem child = item.Items[i];
                treeItemsFlat.Insert(i + index + 1, child);
                child.Position = i + index + 1;
                child.Level = item.Level + 1;

                // Учесть уровень вложенности в title
                listBox.Items.Insert(i + index + 1, child.DisplayTitle);
                if (child.Disabled) listBox.DisabledItemsIndexes.Add(i + index + 1);
            }
            for (int k = index + 1 + item.Items.Count; k < treeItemsFlat.Count; k++) {
                treeItemsFlat[k].Position += item.Items.Count;
            }

            // Children are expanded too according to their Expanded stored state
            foreach (TreeItem child in item.Items.Where(child => child.Expanded)) {
                expand(child);
            }
        }
        private void onItemRemoved(TreeItem treeItem) {
            if (treeItem.Expanded) collapse(treeItem);
            treeItemsFlat.RemoveAt(treeItem.Position);
            listBox.Items.RemoveAt(treeItem.Position);
            for (int j = treeItem.Position; j < treeItemsFlat.Count; j++)
                treeItemsFlat[j].Position--;

            // Cleanup event handler recursively
            unsubscribeFromItem(treeItem, ItemsOnListChanged);

            if (listBox.SelectedItemIndex >= treeItem.Position)
                RaisePropertyChanged("SelectedItem");
        }
 private void unsubscribeFromItem(TreeItem item, ListChangedHandler handler) {
     item.items.ListChanged -= handler;
     item.PropertyChanged -= itemOnPropertyChanged;
     foreach (TreeItem child in item.items) {
         unsubscribeFromItem(child, handler);
     }
 }
 private void subscribeToItem(TreeItem item, ListChangedHandler handler) {
     item.items.ListChanged += handler;
     item.PropertyChanged += itemOnPropertyChanged;
     foreach (TreeItem child in item.items) {
         subscribeToItem(child, handler);
     }
 }