private void ShowVariableEditBox(string initialString)
        {
            // Only clicking on the top-most level item should bring up edit box.
            InspectionViewItem parent = ContainerFromItem(null, inspectionView.SelectedItem);

            if (null == parent || (0 != parent.Level))
            {
                return;
            }

            currentEditingData = (InspectionData)inspectionView.SelectedItem;
            TextBlock nameBlock = FindDescendant <TextBlock>(parent);

            if (nameBlock != null)
            {
                txtVariableEditor.Height = nameBlock.Height;
                txtVariableEditor.Width  = colName.Width;

                GeneralTransform transform     = parent.TransformToAncestor(inspectionView);
                Point            leftTopCoords = transform.Transform(new Point(0, 0));

                if (string.IsNullOrEmpty(initialString))
                {
                    initialString = currentEditingData.DisplayText;
                }

                txtVariableEditor.Margin     = new Thickness(2, leftTopCoords.Y, 0, 0);
                txtVariableEditor.Text       = initialString;
                txtVariableEditor.Visibility = Visibility.Visible;
                txtVariableEditor.Focus();
                txtVariableEditor.SelectAll();
            }
        }
        /// <summary>
        /// An 'Items.Refresh' call erases all the previous expansion data. This recursive
        /// method complements 'CheckExpansion' method where it does the expansion of items
        /// that were expanded before the refresh method closed them.
        /// </summary>
        /// <param name="dataVal">
        /// The Observable Collection that holds all the data for the level below.
        /// Each InspectionData.Derivations is also an Observable Collection.
        /// </param>
        /// <param name="parent">
        /// If parent is null, it means there is no parent and it is the top level data.
        /// Otherwise, send the parent item of the dataVal parameter
        /// </param>
        private void DoExpansion(ICollection <InspectionData> dataVal, InspectionViewItem parent = null)
        {
            if (dataVal == null)
            {
                return;
            }

            foreach (InspectionData item in dataVal)
            {
                if (parent != null)
                {
                    parent.IsExpanded = true;
                    parent.UpdateLayout();
                }

                InspectionViewItem treeListViewItem = ContainerFromItem(parent, item);
                if (null == treeListViewItem)
                {
                    return;
                }

                if (item.IsExpanded)
                {
                    treeListViewItem.IsExpanded = true;
                }

                if (item.HasItems && item.IsExpanded)
                {
                    DoExpansion(item.Derivations, treeListViewItem);
                }
            }
        }
        private InspectionViewItem ContainerFromItem(InspectionViewItem parentItem, object item)
        {
            ItemContainerGenerator generator = inspectionView.ItemContainerGenerator;

            if (null != parentItem)
            {
                generator = parentItem.ItemContainerGenerator;
            }

            return(generator.ContainerFromItem(item) as InspectionViewItem);
        }
        private void HideVariableEditBox(bool commitChanges, bool setFocusOnView)
        {
            if (null == currentEditingData)
            {
                return; // There's no editing item now.
            }
            if (currentEditingData.IsEmptyData == false)
            {
                Solution.Current.RemoveWatchExpressions(currentEditingData.Expression);
            }

            if (!string.IsNullOrEmpty(txtVariableEditor.Text) && (false != commitChanges))
            {
                int index = dataCollection.GetParentIndex(currentEditingData);
                if (index >= 0 && index < dataCollection.Data.Count)
                {
                    bool duplicateExpression = Solution.Current.AddWatchExpressions(txtVariableEditor.Text);
                    if (duplicateExpression == true)
                    {
                        TextEditorControl.Instance.DisplayStatusMessage(StatusTypes.Info, Configurations.WatchWindowDuplicateInfo, 3);
                        return;
                    }

                    dataCollection.UpdateVariableName(txtVariableEditor.Text, index);
                    RefreshInspectionView();
                }
            }

            InspectionViewItem viewItem = ContainerFromItem(null, currentEditingData);

            currentEditingData = null;

            if (null != viewItem)
            {
                viewItem.IsSelected = true;
            }

            txtVariableEditor.Visibility = Visibility.Hidden;
            UIElement elementToFocus = inspectionView;

            if (false != setFocusOnView)
            {
                elementToFocus = TextEditorControl.Instance.textCanvas;
            }

            elementToFocus.Focus();
        }
        private InspectionViewItem ContainerFromItem(InspectionData inspectionData)
        {
            List <InspectionData> reversedDataList = new List <InspectionData>();
            InspectionData        currentData      = inspectionData;

            while (null != currentData)
            {
                reversedDataList.Insert(0, currentData);
                currentData = currentData.ParentData;
            }

            InspectionViewItem viewItem = null;

            foreach (InspectionData data in reversedDataList)
            {
                viewItem = ContainerFromItem(viewItem, data);
            }

            return(viewItem);
        }
        /// <summary>
        /// This method checks all the items in the Watch window and takes note
        /// of what is expanded by toggling the 'isExpanded' flag in the InspectionData class.
        /// This information is later used by 'DoExpansion' to do the actual expansion
        /// </summary>
        /// <param name="dataVal">
        /// The Observable Collection that holds all the data for the level below.
        /// Each InspectionData.Derivations is also an Observable Collection.
        /// </param>
        /// <param name="parent">
        /// If parent is null, it means there is no parent and it is the top level data.
        /// Otherwise, send the parent item of the dataVal parameter
        /// </param>
        void UpdateExpansionStates(ICollection <InspectionData> dataVal, InspectionViewItem parent = null)
        {
            foreach (InspectionData item in dataVal)
            {
                if (item.IsEmptyData)
                {
                    break;
                }

                InspectionViewItem treeListViewItem = ContainerFromItem(parent, item);
                if (null != treeListViewItem)
                {
                    item.IsExpanded = treeListViewItem.IsExpanded;
                }

                if (item.HasItems && item.IsExpanded)
                {
                    UpdateExpansionStates(item.Derivations, treeListViewItem);
                }
            }
        }
        /// <summary>
        /// Event trigger when a keyboard button is pressed in the watch window
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">
        /// Keys accepted:
        /// Delete - to delete an item in the watch window
        /// Enter - to bring up the editing textbox for watch variables
        /// </param>
        private void OnWatchWindowKeyDown(object sender, KeyEventArgs e)
        {
            // Method to delete items from the watch window
            if (e.Key == Key.Delete)
            {
                InspectionData     selectedData = inspectionView.SelectedItem as InspectionData;
                InspectionViewItem parent       = ContainerFromItem(null, selectedData);
                if (null != parent && parent.Level == 0)
                {
                    // Get the sibling item so that we can move selection on it later.
                    InspectionData siblingData = GetSiblingItemFromData(selectedData);

                    InspectionData removedItem = (InspectionData)inspectionView.SelectedItem;
                    if (dataCollection.RemoveInspectionData(inspectionView.SelectedItem))
                    {
                        Solution.Current.RemoveWatchExpressions(removedItem.DisplayText);
                        inspectionView.Items.Refresh();
                    }

                    // Set focus back to the item.
                    InspectionViewItem siblingItem = ContainerFromItem(null, siblingData);
                    if (null != siblingItem)
                    {
                        siblingItem.IsSelected = true;
                    }
                }
            }
            // Method to allow user to bring up the editing textbox in the
            // watch window. This makes usage of watch window easy
            else if (e.Key == Key.Enter)
            {
                ShowVariableEditBox(null);
            }
            else if (e.Key >= Key.A && (e.Key <= Key.Z))
            {
                char character = TextEditorControl.GetKeyboardCharacter(e);
                ShowVariableEditBox(new string(character, 1));
            }
        }
        /// <summary>
        /// Recursive method to iterate through all expanded items and return the expanded index value. Works in
        /// conjunction with the 'GetExpandedIndex' method
        /// </summary>
        /// <param name="dataVal">
        /// The Observable Collection that holds all the data for the level below.
        /// Each InspectionData.Derivations is also an Observable Collection.
        /// </param>
        /// <param name="indexToCheck"> Parent index of the watch window expression </param>
        /// <param name="expandedIndex"> Out parameter, returning expanded index of the watch expression </param>
        /// <param name="parent">
        /// If parent is null, it means there is no parent and it is the top level data.
        /// Otherwise, send the parent item of the dataVal parameter
        /// </param>
        private void ItemExpansionCount(ICollection <InspectionData> dataVal, int indexToCheck, ref int expandedIndex, TreeViewItem parent = null)
        {
            InspectionViewItem parentItem = parent as InspectionViewItem;

            foreach (InspectionData item in dataVal)
            {
                InspectionViewItem treeViewItem = ContainerFromItem(parentItem, item);
                if (treeViewItem.Level == 0)
                {
                    if (dataCollection.GetParentIndex(item) == indexToCheck)
                    {
                        break;
                    }
                }

                expandedIndex++;
                if (item.IsExpanded && item.HasItems)
                {
                    ItemExpansionCount(item.Derivations, indexToCheck, ref expandedIndex, treeViewItem);
                }
            }
        }
        /// <summary>
        /// 'Expander' is part of the toggle button defined in the XAML that shows the [+] or [-]
        /// sign when there are items under the current watch variable that can be inspected.
        /// To maximise efficiency, the expansion of items must happen only when the expander is clicked
        /// when showing [+]. This generated the child items from the Virtual Machine.
        /// </summary>
        /// <param name="sender"> The sender is the Toggle Button</param>
        /// <param name="e"></param>
        private void OnExpanderClicked(object sender, RoutedEventArgs e)
        {
            ToggleButton expanderToggle = (ToggleButton)sender;

            if (null == expanderToggle)
            {
                return;
            }

            // The parent we are trying to locate here is the InspectionViewItem. The
            // expander is buried beneath several layers of stackpanels and grids under the Item
            // and therefore we have to make numerous calls to find the InspectionViewItem.
            InspectionViewItem parent = (InspectionViewItem)VisualTreeHelper.GetParent
                                            (VisualTreeHelper.GetParent
                                                (VisualTreeHelper.GetParent
                                                    (VisualTreeHelper.GetParent
                                                        (VisualTreeHelper.GetParent
                                                            (VisualTreeHelper.GetParent(expanderToggle))))));

            object         data         = ((null == parent) ? null : parent.DataContext);
            InspectionData selectedData = data as InspectionData;

            if (null == selectedData)
            {
                return;
            }

            // expanderToggle.IsChecked == true means the [+] --> [-]
            if (expanderToggle.IsChecked == true)
            {
                parent.IsExpanded = false;
                dataCollection.ExpandInspection(selectedData);
                parent.IsExpanded = true;

                UpdateExpansionStates();
                inspectionView.Items.Refresh();
                DoExpansion(dataCollection.Data);

#if false
                parent.IsExpanded = false;
                InspectionData selectedData = (InspectionData)parent.DataContext;
                dataCollection.ExpandInspection(selectedData);

                // If there is a large amount of data, the user may have to wait.
                // This is indicated by updating the mouse cursor.
                Mouse.SetCursor(Cursors.Wait);
                parent.IsSelected       = true;
                parent.IsExpanded       = true;
                selectedData.IsExpanded = true;

                UpdateExpansionStates();
                inspectionView.Items.Refresh();
                DoExpansion(dataCollection.Data);
                Mouse.SetCursor(Cursors.Arrow);
#endif
            }

            // Select the item that is currently being expanded/collapsed.
            InspectionViewItem itemToSelect = ContainerFromItem(selectedData);
            if (null != itemToSelect)
            {
                itemToSelect.IsSelected = true;
            }
        }