private void AddItemToSelection(MSTreeViewItem newItem)
 {
     if (!_selectedItems.Contains(newItem))
     {
         _selectedItems.Add(newItem);
     }
 }
        void PrevGreaterThan(ItemCollection collection, MSTreeViewItem item)
        {
            int index = collection.IndexOf(item.DataContext);

            if (index < 0)
            {
                return;
            }

            int prev_item = _selectedItems.IndexOf(item) - 1;

            if (prev_item < 0)
            {
                return;
            }

            int prev = collection.IndexOf(_selectedItems[prev_item].DataContext);

            if (prev < 0)
            {
                return;
            }

            if (prev > index)
            {
                _selectedItems.Remove(item);
                _selectedItems.Insert(prev_item, item);
                PrevGreaterThan(collection, item);
            }
        }
        /*
         * public MSTreeViewItem GetItemFromData(int i)
         * {
         *  return (MSTreeViewItem)(this.ItemContainerGenerator.ContainerFromIndex(i));
         * }
         */

        private MSTreeViewItem HasSidlingItem(MSTreeViewItem item)
        {
            MSTreeViewItem parent = item.GetParentTreeViewItem();

            if (parent == null)
            {
                return(null);
            }

            MSTreeViewItem sidling = null;

            foreach (var obj in parent.Items)
            {
                //object i = GetItemFromData(parent.Items.IndexOf(obj));

                // if (obj == null)
                //     continue;
                MSTreeViewItem i = parent.GetChildItemFromData(obj);
                if (i != item && i.IsSelected)
                {
                    sidling = i;
                    break;
                }
            }
            return(sidling);
        }
        /// <summary>
        /// Recursively select all children.
        /// </summary>
        public void SelectAllExpandedChildren()
        {
            if (Items != null && Items.Count > 0)
            {
                if (this.IsExpanded)
                {
                    foreach (var item in Items)
                    {
                        if (item is MSTreeViewItem)
                        {
                            ((MSTreeViewItem)item).SelectAllExpandedChildren();
                        }
                        else
                        {
                            MSTreeViewItem tvItem = this.ItemContainerGenerator.ContainerFromItem(item) as MSTreeViewItem;

                            if (tvItem != null)
                            {
                                tvItem.SelectAllExpandedChildren();
                            }
                        }
                    }
                }
            }

            if (!this.IsSelected)
            {
                this.IsSelected = true;
                ParentMultipleSelectionTreeView.OnSelectionChanges(this);
            }
        }
 private void RemoveItemFromSelection(MSTreeViewItem newItem)
 {
     if (_selectedItems.Contains(newItem))
     {
         _selectedItems.Remove(newItem);
     }
 }
        /// <summary>
        /// Get the node depth.
        /// </summary>
        /// <returns>The int indicating the node depth.</returns>
        public int GetDepth()
        {
            MSTreeViewItem parent = this;

            while (parent.ParentMultipleSelectionTreeViewItem != null)
            {
                return(parent.ParentMultipleSelectionTreeViewItem.GetDepth() + 1);
            }

            return(0);
        }
        /// <summary>
        /// Retrieve the last displayed child node of the given one.
        /// </summary>
        /// <param name="item">The node starting with you want to retrieve the last visible node.</param>
        /// <returns>The last child node that is displayed, or the node itself in case it is not expanded.</returns>
        public MSTreeViewItem GetLastVisibleChildNodeOf(MSTreeViewItem item)
        {
            MSTreeViewItem lastVisibleNode = item;

            // Retrieving last child of last expanded node
            while (lastVisibleNode != null && lastVisibleNode.Items.Count > 0 && lastVisibleNode.IsExpanded)
            {
                lastVisibleNode = lastVisibleNode.ItemContainerGenerator.ContainerFromIndex(lastVisibleNode.Items.Count - 1) as MSTreeViewItem;
            }

            return(lastVisibleNode);
        }
        private void ManageSingleSelection(MSTreeViewItem viewItem)
        {
            bool isViewItemMultipleSelected = viewItem.IsSelected;

            UnselectAll();

            if (isViewItemMultipleSelected)
            {
                viewItem.IsSelected = isViewItemMultipleSelected;
                AddItemToSelection(viewItem);
            }
        }
        private void ManageCtrlSelection(MSTreeViewItem viewItem)
        {
            bool isViewItemMultipleSelected = viewItem.IsSelected;

            if (isViewItemMultipleSelected)
            {
                AddItemToSelection(viewItem);
            }
            else if (!isViewItemMultipleSelected)
            {
                RemoveItemFromSelection(viewItem);
            }
        }
        /// <summary>
        /// Manage keyboard shift select
        /// </summary>
        /// <param name="viewItem"></param>
        private void ManageShiftSelection(MSTreeViewItem viewItem)
        {
            bool isViewItemMultipleSelected = viewItem.IsSelected;

            if (!isViewItemMultipleSelected)
            {
                return;
            }

            MSTreeViewItem sidling = HasSidlingItem(viewItem);

            if (sidling == null)
            {
                return;
            }

            SelectBetween(viewItem, sidling);
        }
        internal void OnSelectionChanges(MSTreeViewItem viewItem)
        {
            MSTreeViewItem newItem = viewItem;

            if (newItem == null)
            {
                return;
            }

            bool isNewItemMultipleSelected = viewItem.IsSelected;

            if (isNewItemMultipleSelected)
            {
                AddItemToSelection(viewItem);
            }
            else
            {
                RemoveItemFromSelection(viewItem);
            }
        }
        //dep
        /// <summary>
        /// ... TODO ...
        /// </summary>
        /// <param name="item1"></param>
        /// <param name="item2"></param>
        /// <returns></returns>
        private bool IsItem1ListedBeforeItem2(MSTreeViewItem item1,
                                              MSTreeViewItem item2)
        {
            /*
             * // Perform a Backword search (up)
             * if (item1.ParentMultipleSelectionTreeViewItem != null) // item1 has a brother!
             * {
             *  ItemCollection brothers = item1.ParentMultipleSelectionTreeViewItem.Items;
             *  int indexOfItem1 = brothers.IndexOf(item1);
             *  int indexOfItem2 = brothers.IndexOf(item2);
             *  if (indexOfItem2 >= 0) //item1 and item2 are brothers
             *  {
             *      return indexOfItem1 < indexOfItem2 ? true : false;
             *  }
             *
             *
             * }
             */

            return(true);
        }
        public void SelectAllExpandedItems()
        {
            if (Items != null && Items.Count > 0)
            {
                foreach (var item in Items)
                {
                    if (item is MSTreeViewItem)
                    {
                        ((MSTreeViewItem)item).SelectAllExpandedChildren();
                    }
                    else
                    {
                        MSTreeViewItem tvItem = this.ItemContainerGenerator.ContainerFromItem(item) as MSTreeViewItem;

                        if (tvItem != null)
                        {
                            tvItem.SelectAllExpandedChildren();
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Retrieve the subsequent node that is at the same level.
        /// </summary>
        /// <param name="item">The node starting with you want to retrieve the subsequent one.</param>
        /// <returns>Null if there is no subsequent node at the same level.</returns>
        public MSTreeViewItem GetNextNodeAtSameLevel(MSTreeViewItem item)
        {
            if (item == null)
            {
                return(null);
            }

            MSTreeViewItem nextNodeAtSameLevel = null;

            ItemsControl parentControl = item.ParentItemsControl;

            if (parentControl != null)
            {
                int index = parentControl.ItemContainerGenerator.IndexFromContainer(item);
                if (index != parentControl.Items.Count - 1) // if this is not the last item
                {
                    nextNodeAtSameLevel = parentControl.ItemContainerGenerator.ContainerFromIndex(index + 1) as MSTreeViewItem;
                }
            }

            return(nextNodeAtSameLevel);
        }
        private void SelectBetween(MSTreeViewItem item1, MSTreeViewItem item2)
        {
            //if (item1.Parent != item2.Parent)
            //    return;

            MSTreeViewItem parent  = item1.GetParentTreeViewItem();
            int            index_1 = parent.Items.IndexOf(item1.DataContext);
            int            index_2 = parent.Items.IndexOf(item2.DataContext);

            if (index_1 < index_2)
            {
                for (int i = index_1; i < index_2; i++)
                {
                    MSTreeViewItem item = parent.GetChildItemFromData(parent.Items[i]);
                    if (item == null)
                    {
                        continue;
                    }

                    item.Select();
                }
            }
            if (index_1 > index_2)
            {
                for (int i = index_1; i > index_2; i--)
                {
                    MSTreeViewItem item = parent.GetChildItemFromData(parent.Items[i]);
                    if (item == null)
                    {
                        continue;
                    }

                    item.Select();
                }
            }
            SortSelectedItems(parent.Items);
        }
        internal void OnViewItemMouseDown(MSTreeViewItem viewItem)
        {
            MSTreeViewItem newItem = viewItem;

            if (newItem == null)
            {
                return;
            }

            switch (this.SelectionMode)
            {
            case SelectionModalities.MultipleSelectionOnly:
                ManageCtrlSelection(newItem);
                break;

            case SelectionModalities.SingleSelectionOnly:
                ManageSingleSelection(newItem);
                break;

            case SelectionModalities.KeyboardModifiersMode:
                if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
                {
                    ManageShiftSelection(newItem);
                }
                else if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
                {
                    ManageCtrlSelection(newItem);
                }
                else
                {
                    ManageSingleSelection(newItem);
                }
                break;
            }
            _lastClickedItem = viewItem.IsSelected ? viewItem : null;
        }
 /// <summary>
 /// ... TODO ...
 /// </summary>
 /// <param name="fromItem"></param>
 /// <param name="toItem"></param>
 private void SelectRange(MSTreeViewItem fromItem,
                          MSTreeViewItem toItem)
 {
 }
        protected override void OnKeyDown(KeyEventArgs e)
        {
            try
            {
                MSTreeViewItem itemToSelect = null;

                if (e.Key == Key.Left)
                {
                    this.IsExpanded = false;
                }
                else if (e.Key == Key.Right)
                {
                    this.IsExpanded = true;
                }
                else if (e.Key == Key.Up)
                {
                    // In this case we need to select the last child of the last expandend node of
                    // - the previous at the same level (if this index node is NOT 0)
                    // - the parent node (if this index node is 0)

                    int currentNodeIndex = this.ParentItemsControl.ItemContainerGenerator.IndexFromContainer(this);

                    if (currentNodeIndex == 0)
                    {
                        itemToSelect = this.ParentMultipleSelectionTreeViewItem;
                    }
                    else
                    {
                        MSTreeViewItem tmp = null;
                        tmp          = GetPreviousNodeAtSameLevel(this);
                        itemToSelect = GetLastVisibleChildNodeOf(tmp);
                    }
                }
                else if (e.Key == Key.Down)
                {
                    // In this case we need to select:
                    // - the first child node (if this node is expanded)
                    // - the next at the same level (if this not the last child)
                    // - the next at the same level of the parent node (if this is the last child)

                    if (this.IsExpanded && this.Items.Count > 0)
                    { // Select first Child
                        itemToSelect = this.ItemContainerGenerator.ContainerFromIndex(0) as MSTreeViewItem;
                    }
                    else
                    {
                        itemToSelect = GetNextNodeAtSameLevel(this);

                        if (itemToSelect == null) // current node has no subsequent node at the same level
                        {
                            MSTreeViewItem tmp = this.ParentMultipleSelectionTreeViewItem;

                            while (itemToSelect == null && tmp != null) // searhing for the first parent that has a subsequent node at the same level
                            {
                                itemToSelect = GetNextNodeAtSameLevel(tmp);
                                tmp          = tmp.ParentMultipleSelectionTreeViewItem;
                            }
                        }
                    }
                }

                if (itemToSelect != null)
                {
                    itemToSelect.Focus();
                    itemToSelect.IsSelected = true;
                    ParentMultipleSelectionTreeView.OnViewItemMouseDown(itemToSelect);
                }
            }
            catch (Exception) { /* Silently ignore */ }

            // Don't bubble up the event. (I'm sure you know difference between Bubble and Tunnel events in WPF...)
            e.Handled = true;
        }