private void UpdateSelectedItems(TreeListViewItem viewItem)
 {
     if (viewItem.IsSelected)
     {
         if (!_selectedItems.Contains(viewItem))
             _selectedItems.Add(viewItem);
     }
     else
     {
         _selectedItems.Remove(viewItem);
     }
 }
        private void ExtendSelectionTo(TreeListViewItem rangeSelectionEnd)
        {
            //if _rangeSelectionStart == null then it is just a single select so: _rangeSelectionStart=rangeSelectionEnd
            if (_rangeSelectionStart == null)
            {
                _rangeSelectionStart = rangeSelectionEnd;
                UpdateSelectedItems(rangeSelectionEnd);
            }
            else
            {
                //SelectAllItemsBetween _rangeSelectionStart and rangeSelectionEnd
                var descendants = Descendants()
                    //Filter out parent rows, unless a parent row was explicitly selected.
                   .Where(child =>
                       CanUpdateParents
                       || child.ParentTreeListViewItem != null
                       || ReferenceEquals(child, _rangeSelectionStart)
                       || ReferenceEquals(child, rangeSelectionEnd))
                   .ToList();

                var startIdx = descendants.IndexOf(_rangeSelectionStart);
                var endIdx = descendants.IndexOf(rangeSelectionEnd);

                if (startIdx > endIdx)
                {
                    endIdx = Interlocked.Exchange(ref startIdx, endIdx);
                }
                var lastRangeSelection = _rangeSelection.ToArray().ToList();
                _rangeSelection.Clear();

                using (SupressSelectionHandler())
                {
                    for (int i = startIdx; i <= endIdx; i++)
                    {
                        var item = descendants[i];
                        if (!item.IsSelected || ReferenceEquals(item, rangeSelectionEnd))
                        {
                            item.IsSelected = true;
                            UpdateSelectedItems(item);
                            _rangeSelection.Add(item);
                        }
                        lastRangeSelection.Remove(item);
                    }
                    foreach (var oldItem in lastRangeSelection)
                    {
                        oldItem.IsSelected = false;
                        UpdateSelectedItems(oldItem);
                    }
                }
            }
        }
        private void SelectSingleItem(TreeListViewItem viewItem)
        {
            var selectedItems = Descendants()
                .Where(child => child.IsSelected
                                && !ReferenceEquals(child, viewItem)
                                && (CanUpdateParents || child.ParentTreeListViewItem != null))
                .ToList();

            var isSelected = viewItem.IsSelected;
            using (SupressSelectionHandler())
            {
                foreach (var selectedItem in selectedItems)
                {
                    selectedItem.IsSelected = false;
                    UpdateSelectedItems(selectedItem);
                }
                //Ensure that modifications to other items have not unselected this item.
                viewItem.IsSelected = isSelected;
            }

            UpdateSelectedItems(viewItem);
        }
        internal void OnItemSelected(TreeListViewItem viewItem)
        {
            if (viewItem == null || IgnoreSelectionChanged())
                return;

            if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
            {
                ExtendSelectionTo(viewItem);
            }
            else
            {
                _rangeSelection.Clear();
                if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
                {
                    UpdateSelectedItems(viewItem);
                }
                else
                {
                    SelectSingleItem(viewItem);
                }

                _rangeSelectionStart = viewItem.IsSelected ? viewItem : null;
            }
        }
        /// <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>
        private static TreeListViewItem GetNextNodeAtSameLevel(TreeListViewItem item)
        {
            if (item == null)
                return null;

            TreeListViewItem nextNodeAtSameLevel = null;

            var 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 TreeListViewItem;
                }
            }

            return nextNodeAtSameLevel;
        }
        /// <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>
        private static TreeListViewItem GetLastVisibleChildNodeOf(TreeListViewItem item)
        {
            var 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 TreeListViewItem;

            return lastVisibleNode;
        }