private Dictionary<string, string> GetDmuIdFromNameLookup()
        {
            // First get all DMU entries
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            DmuAccess.AddDescriptionOfMapUnits();

            // Pass these records into a new Dictionary correlating ID to HierarchyKey
            Dictionary<string, string> idDmuDictionary = new Dictionary<string, string>();
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> aDictionaryEntry in DmuAccess.DescriptionOfMapUnitsDictionary)
            {
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = (DescriptionOfMapUnitsAccess.DescriptionOfMapUnit)aDictionaryEntry.Value;
                if (thisDmuEntry.ParagraphStyle.Contains("Heading") == true) { idDmuDictionary.Add(thisDmuEntry.Name, thisDmuEntry.DescriptionOfMapUnits_ID); }
                else { idDmuDictionary.Add(thisDmuEntry.MapUnit + " - " + thisDmuEntry.Name, thisDmuEntry.DescriptionOfMapUnits_ID); }

            }

            return idDmuDictionary;
        }
        private IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>> GetDmuSortedByHierarchy()
        {
            // Get All DescriptionOfMapUnits.
            DescriptionOfMapUnitsAccess DmuAccess;
            DmuAccess = new DescriptionOfMapUnitsAccess(ArcMap.Editor.EditWorkspace);
            DmuAccess.AddDescriptionOfMapUnits();

            // Sort using Linq syntax
            var sortedDmuEntries = (
                from entry in DmuAccess.DescriptionOfMapUnitsDictionary
                orderby ((DescriptionOfMapUnitsAccess.DescriptionOfMapUnit)entry.Value).HierarchyKey ascending
                select entry);

            return sortedDmuEntries;
        }
        private void DeleteAllChildren(string parentKey)
        {
            // Get DMU Access Class
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // Get the children
            var sortedChildren = GetSortedChildren(parentKey);

            // Loop through them, delete each one
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> anEntry in sortedChildren)
            {
                // Get the DMU entry for this entry
                DmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + anEntry.Value.DescriptionOfMapUnits_ID + "'");
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = DmuAccess.DescriptionOfMapUnitsDictionary[anEntry.Value.DescriptionOfMapUnits_ID];

                /// Delete related record in the Extended Attributes table
                deleteExtendedAtrributesRecord(thisDmuEntry.MapUnit);
                /// Delete related lithology records
                deleteLithologyRecord(thisDmuEntry.MapUnit);

                // Delete it
                DmuAccess.DeleteDescriptionOfMapUnits(thisDmuEntry);

                // Delete its children
                DeleteAllChildren(thisDmuEntry.HierarchyKey);
            }
        }
        private void UpdateChildrenKeys(string oldParentKey, string newParentKey, IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>> sortedChildren = null)
        {
            // If a set of children are not passed in to update, then get them based on the oldParentKey that is sent in
            if (sortedChildren == null) { sortedChildren = GetSortedChildren(oldParentKey); }

            // Get a DMU Access object to perform an update
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // Cycle through the children
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> anEntry in sortedChildren)
            {
                // Grab, adjust the hierarchy information
                string thisKey = anEntry.Value.HierarchyKey;
                string thisKeyValue = thisKey.Substring(thisKey.Length - 4);
                string newKey = newParentKey + "." + thisKeyValue;

                // Get the DMU entry for this entry
                DmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + anEntry.Value.DescriptionOfMapUnits_ID + "'");
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = DmuAccess.DescriptionOfMapUnitsDictionary[anEntry.Value.DescriptionOfMapUnits_ID];

                // Update its key
                thisDmuEntry.HierarchyKey = newKey;
                DmuAccess.UpdateDescriptionOfMapUnit(thisDmuEntry);

                // Update its children's keys
                UpdateChildrenKeys(thisKey, newKey);
            }

            // Save the changes
            DmuAccess.SaveDescriptionOfMapUnits();
        }
        private void trvLegendItems_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            // Get the dragged node, and the associated DMU entry
            TreeNode draggedNode = e.Data.GetData((new TreeNode()).GetType()) as TreeNode;
            DescriptionOfMapUnitsAccess dmuFinder = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            dmuFinder.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + draggedNode.Name + "'");
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit draggedDmuEntry = dmuFinder.DescriptionOfMapUnitsDictionary[draggedNode.Name];

            // Cast the cursor's location into Treeview-coordinates
            System.Drawing.Point dragLocation = (sender as TreeView).PointToClient(new System.Drawing.Point(e.X, e.Y));

            // Find out what the drag is over
            TreeNode destinationNode = trvLegendItems.GetNodeAt(dragLocation);
            if (destinationNode == null) { return; }

            // Ask the user how to perform the drop
            dropChooser dropChoiceForm = new dropChooser();
            dropChoiceForm.ShowDialog();

            // Bail if they canceled
            if (dropChoiceForm.Canceled == true) { return; }

            // Before making changes, gather the children of the dragged node
            var draggedChildren = GetSortedChildren(draggedDmuEntry.HierarchyKey);

            // First, remove the dragged node from the hierarchy
            RemoveItemFromHierarchy(draggedDmuEntry.HierarchyKey);

            // Get the dropped item's DMU entry
            dmuFinder.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + destinationNode.Name + "'");
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit destinationDmuEntry = dmuFinder.DescriptionOfMapUnitsDictionary[destinationNode.Name];

            // Next, insert the node in the new location
            string newHierarchyKey = "";
            int newKeyValue = 0;

            // Depending on the user's choice, drop appropriately
            switch (dropChoiceForm.DropAsChild)
            {
                case true:
                    // Child drop, put it at the end of the block
                    newHierarchyKey = GetNewHierarchyKey(destinationDmuEntry.HierarchyKey);
                    break;

                case false:
                    // Sibling drop - above or below?
                    switch (dropChoiceForm.DropBelow)
                    {
                        case true:
                            // Drop below
                            newKeyValue = int.Parse(destinationDmuEntry.HierarchyKey.Substring(destinationDmuEntry.HierarchyKey.Length - 4)) + 1;
                            break;

                        case false:
                            // Drop above
                            newKeyValue = int.Parse(destinationDmuEntry.HierarchyKey.Substring(destinationDmuEntry.HierarchyKey.Length - 4));
                            break;
                    }

                    // Build the new Hierarchy Key
                    if (destinationDmuEntry.HierarchyKey.Length == 4) { newHierarchyKey = newKeyValue.ToString().PadLeft(4, '0'); }
                    else { newHierarchyKey = destinationDmuEntry.HierarchyKey.Remove(destinationDmuEntry.HierarchyKey.Length - 5) + "." + newKeyValue.ToString().PadLeft(4, '0'); }
                    break;
            }

            // Take care of rebuilding the hierarchy due to the insert
            //  I need to pass in these children because after making any adjustments to the hierarchy
            //  (RemoveFromHierarchy call above), I cannot rely on hierarchy keys to be truthful as to
            //  who was the initial parent. That is, at this point trying to find the inital children
            //  of the dragged node is impossible.
            InsertItemIntoHierarchy(draggedDmuEntry, newHierarchyKey, draggedChildren);

            // Lastly, clear all highlighted nodes, repopulate the tree
            ClearHighlights(trvLegendItems.Nodes);
            ClearMapUnitInput();
            PopulateMainLegendTree();
        }
        private void trvLegendItems_AfterSelect(object sender, TreeViewEventArgs e)
        {
            // -----------------------------------------------------------------------------
            // -----------------------------------------------------------------------------
            //  Populate the input controls based on the selected node
            // -----------------------------------------------------------------------------
            // -----------------------------------------------------------------------------

            // Make sure that something is selected
            if (e.Node == null) { return; }

            // Get the selected DMU entry
            DescriptionOfMapUnitsAccess dmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + e.Node.Name + "'");
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = dmuAccess.DescriptionOfMapUnitsDictionary[e.Node.Name];

            // Populate controls
            PopulateInputControls(thisDmuEntry);

            // Get the related standard lithology entry
            initLithListBox(thisDmuEntry.MapUnit);

            /// Initialize the age tab
            initAgeTab(thisDmuEntry.MapUnit);
        }
        private void tlsbtnShowCopyPanel_Click(object sender, EventArgs e)
        {
            #region "Open the Database to Copy From"

            findDatabase:
            // Check the registry
            string regValue = commonFunctions.ReadReg("Software\\NCGMPTools", "getSqlDatabase");

            // Find a Database
            IWorkspaceFactory wsFact = null;
            IWorkspace openedWorkspace = null;

            // Browse for a file, personal or SDE geodatabase
            IGxObjectFilter objectFilter = new GxFilterWorkspaces();
            IGxObject openedObject = commonFunctions.OpenArcFile(objectFilter, "Please select an NCGMP database");
            if (openedObject == null) { return; }

            // Check to see if it is a File, Personal or SDE database, create appropriate workspace factory
            string pathToOpen = null;

            switch (openedObject.Category)
            {
                case "Personal Geodatabase":
                    wsFact = new AccessWorkspaceFactoryClass();
                    pathToOpen = openedObject.FullName;
                    break;
                case "File Geodatabase":
                    wsFact = new FileGDBWorkspaceFactoryClass();
                    pathToOpen = openedObject.FullName;
                    break;
                case "Spatial Database Connection":
                case "Database Connection":
                    wsFact = new SdeWorkspaceFactoryClass();
                    IGxRemoteDatabaseFolder remoteDatabaseFolder = (IGxRemoteDatabaseFolder)openedObject.Parent;
                    pathToOpen = remoteDatabaseFolder.Path + openedObject.Name;
                    break;
                default:
                    break;
            }
            openedWorkspace = wsFact.OpenFromFile(pathToOpen, 0);

            // Check to see if the database is valid NCGMP
            bool isValid = ncgmpChecks.IsWorkspaceMinNCGMPCompliant(openedWorkspace);
            if (isValid == false)
            {
                MessageBox.Show("The selected database is not a valid NCGMP database.", "NCGMP Toolbar");
                goto findDatabase;
            }
            //else
            //{
            //    isValid = ncgmpChecks.IsSysInfoPresent(openedWorkspace);
            //    if (isValid == false)
            //    {
            //        MessageBox.Show("In order to use these tools, the NCGMP database must contain a SysInfo table.", "NCGMP Toolbar");
            //        goto findDatabase;
            //    }
            //}
            #endregion

            // Show the copy form
            sourceLegendItemSelection sourceForm = new sourceLegendItemSelection(openedWorkspace);
            sourceForm.ShowDialog();

            // Bail if they canceled
            if (sourceForm.Canceled == true) { return; }

            // Get the Ids from the form, then close it
            if (sourceForm.idsToCopy.Count == 0) { sourceForm.Close(); return; }
            List<string> idsToCopy = sourceForm.idsToCopy;
            sourceForm.Close();

            // Build the Query to get the records to copy
            string sqlWhereClause = "DescriptionOfMapUnits_ID = '";
            foreach (string idValue in idsToCopy) { sqlWhereClause += idValue + "' OR DescriptionOfMapUnits_ID = '"; }

            // Get the records
            if (sqlWhereClause == "DescriptionOfMapUnits_ID = '") { return; }
            DescriptionOfMapUnitsAccess sourceDmu = new DescriptionOfMapUnitsAccess(openedWorkspace);
            sourceDmu.AddDescriptionOfMapUnits(sqlWhereClause.Remove(sqlWhereClause.Length - 32));

            // Get the next new Hierarchy Key
            string newHierarchy = GetNewHierarchyKey();
            int newValue = int.Parse(newHierarchy.Substring(newHierarchy.Length - 4));

            // Loop through the source records, add them to the target legend after adjusting the Hierarchy
            DescriptionOfMapUnitsAccess targetDmu = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> sourceEntry in sourceDmu.DescriptionOfMapUnitsDictionary)
            {
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit sourceDmuEntry = sourceEntry.Value;
                string thisHierachyKey = newValue.ToString().PadLeft(4, '0');

                targetDmu.NewDescriptionOfMapUnit(sourceDmuEntry.MapUnit, sourceDmuEntry.Name, sourceDmuEntry.FullName, sourceDmuEntry.Label,
                    sourceDmuEntry.Age, sourceDmuEntry.Description, thisHierachyKey,
                    sourceDmuEntry.ParagraphStyle, sourceDmuEntry.AreaFillRGB, sourceDmuEntry.AreaFillPatternDescription,
                    commonFunctions.GetCurrentDataSourceID(), sourceDmuEntry.GeneralLithology, sourceDmuEntry.GeneralLithologyConfidence);

                newValue++;
            }

            // Save the target Dmu
            targetDmu.SaveDescriptionOfMapUnits();

            // Refresh the tree
            ClearMapUnitInput();
            PopulateMainLegendTree();
        }
        private void tlsbtnRemoveLegendItem_Click(object sender, EventArgs e)
        {
            // Get DMU Access Class
            DescriptionOfMapUnitsAccess dmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // Find out if the selected node has children
            if (trvLegendItems.SelectedNode.Nodes.Count > 0)
            {
                // This node has children, ensure they want it all gone
                DialogResult result = MessageBox.Show("If you delete this entry, all of its children will be removed as well. Do you want to continue?", "NCGMP Tools", MessageBoxButtons.YesNo);
                if (result != DialogResult.Yes) { return; }

                // They want to continue. First delete this one
                dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + trvLegendItems.SelectedNode.Name + "'");
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisEntry = dmuAccess.DescriptionOfMapUnitsDictionary[trvLegendItems.SelectedNode.Name];

                /// Delete related record in the Extended Attributes table
                deleteExtendedAtrributesRecord(thisEntry.MapUnit);
                /// Delete related lithology records
                deleteLithologyRecord(thisEntry.MapUnit);

                dmuAccess.DeleteDescriptionOfMapUnits(thisEntry);

                // Now Delete all children
                DeleteAllChildren(thisEntry.HierarchyKey);

                // Adjust the Hierarchy
                RemoveItemFromHierarchy(thisEntry.HierarchyKey);
            }
            else
            {
                // This node has no children, simply delete it
                dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + trvLegendItems.SelectedNode.Name + "'");
                DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisEntry = dmuAccess.DescriptionOfMapUnitsDictionary[trvLegendItems.SelectedNode.Name];

                /// Delete related record in the Extended Attributes table
                deleteExtendedAtrributesRecord(thisEntry.MapUnit);
                /// Delete related lithology records
                deleteLithologyRecord(thisEntry.MapUnit);

                dmuAccess.DeleteDescriptionOfMapUnits(thisEntry);

                // Remove this item from the Hierarchy - Update its siblings and children
                RemoveItemFromHierarchy(thisEntry.HierarchyKey);
            }

            // Clear Inputs
            ClearMapUnitInput();

            //Re-populate the Treeview
            PopulateMainLegendTree();
        }
        private void tlsbtnAssignUnit_Click(object sender, EventArgs e)
        {
            // Find the selected DMU Entry
            string dmuID = trvLegendItems.SelectedNode.Name;
            if (dmuID == null) { return; }

            DescriptionOfMapUnitsAccess dmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + dmuID + "'");
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit dmuEntry = dmuAccess.DescriptionOfMapUnitsDictionary[dmuID];

            // Layers that can have Map Units Assigned
            string[] polyLayers = { "MapUnitPolys", "CMUMapUnitPolys", "CSAMapUnitPolys", "CSBMapUnitPolys", "CSCMapUnitPolys", "CSDMapUnitPolys", "CSEMapUnitPolys", "CSFMapUnitPolys" };

            // Loop through each layer which can have Map Units Assigned
            for (int i = 0; i < polyLayers.Length; i++)
            {
                try
                {
                    // Get selected polygons
                    IFeatureLayer mapUnitPolysLayer = commonFunctions.FindFeatureLayer(m_theWorkspace, polyLayers[i]);

                    // Find out if there are selected features
                    IFeatureSelection featureSelection = (IFeatureSelection)mapUnitPolysLayer;
                    ISelectionSet theSelection = featureSelection.SelectionSet;

                    if (theSelection.Count != 0)
                        assignMapUnit(theSelection, mapUnitPolysLayer, dmuEntry);
                }
                catch { }
            }
        }
        private void saveMapUnit()
        {
            // Get attributes from the form
            string thisDmuAge = txtMapUnitAge.Text;
            string thisDmuDefinitionSourceID = commonFunctions.GetCurrentDataSourceID();
            string thisDmuDescription = txtMapUnitDescription.Text;
            string thisDmuFullName = txtMapUnitFullName.Text;
            string thisDmuLabel = txtMapUnitAbbreviation.Text;
            string thisDmuMapUnit = txtMapUnitAbbreviation.Text;
            string thisDmuName = txtUnitName.Text;

            // These attributes are dependant on whether this is a heading or not
            string thisDmuParagraphStyle = "";
            string thisDmuAreaFillRGB = "";
            if (chkIsHeading.Checked == true)
            {
                thisDmuParagraphStyle = "Heading";
                thisDmuAreaFillRGB = "";
            }
            else
            {
                thisDmuParagraphStyle = "Standard";
                thisDmuAreaFillRGB = pnlColor.BackColor.R + ";" + pnlColor.BackColor.G + ";" + pnlColor.BackColor.B;
            }

            // Get the DMU reference that will be used to provide table access
            DescriptionOfMapUnitsAccess dmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // Set the variable to represent the updated Dmu entry in the case of an update. This will be used to update polygons later
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit dmuEntry = new DescriptionOfMapUnitsAccess.DescriptionOfMapUnit();

            switch (m_ThisIsAnUpdate)
            {
                case true:
                    // Get the DMU entry that should be updated
                    dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + trvLegendItems.SelectedNode.Name + "'");
                    dmuEntry = dmuAccess.DescriptionOfMapUnitsDictionary[trvLegendItems.SelectedNode.Name];

                    // Add attributes from the form
                    dmuEntry.Age = thisDmuAge;
                    dmuEntry.DescriptionSourceID = thisDmuDefinitionSourceID;
                    dmuEntry.Description = thisDmuDescription;
                    dmuEntry.FullName = thisDmuFullName;
                    dmuEntry.Label = thisDmuLabel;
                    dmuEntry.MapUnit = thisDmuMapUnit;
                    dmuEntry.Name = thisDmuName;
                    dmuEntry.RequiresUpdate = true;

                    // These attributes are dependant on whether this is a heading or not
                    if (chkIsHeading.Checked == true)
                    {
                        dmuEntry.ParagraphStyle = thisDmuParagraphStyle;
                        dmuEntry.AreaFillRGB = thisDmuAreaFillRGB;
                    }
                    else
                    {
                        dmuEntry.ParagraphStyle = thisDmuParagraphStyle;
                        dmuEntry.AreaFillRGB = thisDmuAreaFillRGB;
                    }

                    // Perform the update
                    dmuAccess.UpdateDescriptionOfMapUnit(dmuEntry);

                    break;

                case false:
                    // This is a new entry, get an Hierarchy Key
                    string thisDmuHierarchyKey = GetNewHierarchyKey();

                    // Add the record
                    dmuAccess.NewDescriptionOfMapUnit(thisDmuMapUnit, thisDmuName, thisDmuFullName,
                        thisDmuLabel, thisDmuAge, thisDmuDescription,
                        thisDmuHierarchyKey, thisDmuParagraphStyle, thisDmuAreaFillRGB,
                        "", thisDmuDefinitionSourceID, "", "");

                    break;
            }

            // All done - save
            dmuAccess.SaveDescriptionOfMapUnits();

            // Refresh the tree
            PopulateMainLegendTree();

            // Update polys
            if ((m_ThisIsAnUpdate == true) && (m_theOldMapUnitName != null)) { UpdatePolygons(m_theOldMapUnitName, dmuEntry); }

            // Clear Inputs
            ClearMapUnitInput();
        }
        private void RemoveItemFromHierarchy(string keyBeingRemoved)
        {
            // Get the parent Hierearchy Key
            string parentKey;
            if (keyBeingRemoved.Length == 4) { parentKey = null; }
            else { parentKey = keyBeingRemoved.Remove(keyBeingRemoved.Length - 5); }

            int removedKeyValue = int.Parse(keyBeingRemoved.Substring(keyBeingRemoved.Length - 4));

            // Get the children of the removed node's parent
            var sortedChildren = GetSortedChildren(parentKey);

            // Get a DMU Access object to perform an update
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // Cycle through the children
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> anEntry in sortedChildren)
            {
                // Grab the hierarchy information
                string thisKey = anEntry.Value.HierarchyKey;
                int thisKeyValue = int.Parse(thisKey.Substring(thisKey.Length - 4));

                // If the value is greater than the removed key, decrement by one, and update children
                if (thisKeyValue > removedKeyValue)
                {
                    string newKey;
                    if (parentKey == null) { newKey = (thisKeyValue - 1).ToString().PadLeft(4, '0'); }
                    else { newKey = parentKey + "." + (thisKeyValue - 1).ToString().PadLeft(4, '0'); }

                    // Get the DMU entry for this entry
                    DmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + anEntry.Value.DescriptionOfMapUnits_ID + "'");
                    DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = DmuAccess.DescriptionOfMapUnitsDictionary[anEntry.Value.DescriptionOfMapUnits_ID];

                    // Update its key
                    thisDmuEntry.HierarchyKey = newKey;
                    DmuAccess.UpdateDescriptionOfMapUnit(thisDmuEntry);

                    // Update its children's keys
                    UpdateChildrenKeys(thisKey, newKey);
                }
            }

            // Save the changes
            DmuAccess.SaveDescriptionOfMapUnits();
        }
        private void InsertItemIntoHierarchy(DescriptionOfMapUnitsAccess.DescriptionOfMapUnit theInsertedDmuEntry, string theNewHierarchyKey,
            IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>> thisItemsChildren)
        {
            // Get the insert location parent Hierarchy Key
            string parentKey;
            if (theNewHierarchyKey.Length == 4) { parentKey = null; }
            else { parentKey = theNewHierarchyKey.Remove(theNewHierarchyKey.Length - 5); }

            int newKeyValue = int.Parse(theNewHierarchyKey.Substring(theNewHierarchyKey.Length - 4));

            // Get the children of the inserted item's new parent
            var sortedChildren = GetSortedChildren(parentKey);

            // Get a DMU Access object to perform an update
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);

            // I need to have each of the entry's children gathered before I start updating them.
            // What a f*****g mess.
            Dictionary<string, IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>>> theChildren = new Dictionary<string, IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>>>();
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> anEntry in sortedChildren)
            {
                theChildren.Add(anEntry.Value.DescriptionOfMapUnits_ID, GetSortedChildren(anEntry.Value.HierarchyKey));
            }

            // Cycle through these children
            foreach (KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit> anEntry in sortedChildren)
            {
                // Grab this item's hierarchy info
                string thisKey = anEntry.Value.HierarchyKey;
                int thisKeyValue = int.Parse(thisKey.Substring(thisKey.Length - 4));

                // If the value is greater than or equal to the inserted item's new hierarchy value, increment by one, update children
                if (thisKeyValue >= newKeyValue)
                {
                    string thisNewKey;
                    if (parentKey == null) { thisNewKey = (thisKeyValue + 1).ToString().PadLeft(4, '0'); }
                    else { thisNewKey = parentKey + "." + (thisKeyValue + 1).ToString().PadLeft(4, '0'); }

                    // Get the DMU entry for this entry
                    DmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + anEntry.Value.DescriptionOfMapUnits_ID + "'");
                    DescriptionOfMapUnitsAccess.DescriptionOfMapUnit thisDmuEntry = DmuAccess.DescriptionOfMapUnitsDictionary[anEntry.Value.DescriptionOfMapUnits_ID];

                    // Update its key
                    thisDmuEntry.HierarchyKey = thisNewKey;
                    DmuAccess.UpdateDescriptionOfMapUnit(thisDmuEntry);

                    // Update its children's keys, gathered beforehand
                    UpdateChildrenKeys(thisKey, thisNewKey, theChildren[thisDmuEntry.DescriptionOfMapUnits_ID]);
                }
            }

            // Update the Children of the dragged item using the collection of children passed in
            UpdateChildrenKeys(theInsertedDmuEntry.HierarchyKey, theNewHierarchyKey, thisItemsChildren);

            // Update the dragged item itself
            theInsertedDmuEntry.HierarchyKey = theNewHierarchyKey;
            DmuAccess.UpdateDescriptionOfMapUnit(theInsertedDmuEntry);

            // Save changes
            DmuAccess.SaveDescriptionOfMapUnits();
        }
        private IOrderedEnumerable<KeyValuePair<string, DescriptionOfMapUnitsAccess.DescriptionOfMapUnit>> GetSortedChildren(string parentKey = null)
        {
            // Get the children of a given parent, sorted on HierarchyKey
            // First get all DMU entries
            DescriptionOfMapUnitsAccess DmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            DmuAccess.AddDescriptionOfMapUnits();

            if (parentKey != null)
            {
                // Sort and filter using Linq syntax
                var sortedDmuEntries = (
                    from entry in DmuAccess.DescriptionOfMapUnitsDictionary
                    where ((entry.Value.HierarchyKey.Length == parentKey.Length + 5) && (entry.Value.HierarchyKey.StartsWith(parentKey)))
                    orderby entry.Value.HierarchyKey ascending
                    select entry);

                return sortedDmuEntries;
            }
            else
            {
                // Just return the root-level stuff
                var sortedDmuEntries = (
                    from entry in DmuAccess.DescriptionOfMapUnitsDictionary
                    where entry.Value.HierarchyKey.Length == 4
                    orderby entry.Value.HierarchyKey ascending
                    select entry);

                return sortedDmuEntries;

            }
        }
        private Dictionary<string, object> BuildDataAccessFromSelection()
        {
            // Will be building SQL Where Clauses for each possible selected thing
            string MapUnitPolysSearch = "MapUnitPolys_ID = '";
            string OverlayPolysSearch = "OverlayPolys_ID = '";
            string ContactsAndFaultsSearch = "ContactsAndFaults_ID = '";
            string OtherLinesSearch = "OtherLines_ID = '";
            string StationPointsSearch = "StationPoints_ID = '";
            string SamplePointsSearch = "SamplePoints_ID = '";
            string OrientationDataPointsSearch = "OrientationDataPoints_ID = '";
            string GlossarySearch = "Glossary_ID = '";
            string NotesSearch = "Notes_ID = '";
            string RelatedDocumentsSearch = "RelatedDocuments_ID = '";
            string DataSourcesSearch = "DataSources_ID = '";
            string DescriptionOfMapUnitsSearch = "DescriptionOfMapUnits_ID = '";

            // This object will be populated and returned
            Dictionary<string, object> dataAccessClasses = new Dictionary<string, object>();

            #region Selected FEATURES
            // Get an enumeration of the selected features
            IEnumFeature selectionEnum = ArcMap.Document.FocusMap.FeatureSelection as IEnumFeature;

            // Loop through the features to build queries to find the features
            IRow thisFeature = selectionEnum.Next() as IRow;

            while (thisFeature != null)
            {
                // Get the Table Name
                string tableName = (thisFeature.Table as IDataset).Name;

                // Parse the table name in order to strip out unneccessary bits of SDE tables
                ISQLSyntax nameParser = (ISQLSyntax)m_theWorkspace;
                string parsedDbName, parsedOwnerName, parsedTableName;
                nameParser.ParseTableName(tableName, out parsedDbName, out parsedOwnerName, out parsedTableName);

                // Build the SQL Where Clause depending on the table...
                switch (parsedTableName)
                {
                    case "MapUnitPolys":
                        MapUnitPolysSearch += thisFeature.get_Value(thisFeature.Table.FindField("MapUnitPolys_ID")) + "' OR MapUnitPolys_ID = '";
                        break;
                    case "OverlayPolys":
                        OverlayPolysSearch += thisFeature.get_Value(thisFeature.Table.FindField("OverlayPolys_ID")) + "' OR OverlayPolys_ID = '";
                        break;
                    case "ContactsAndFaults":
                        ContactsAndFaultsSearch += thisFeature.get_Value(thisFeature.Table.FindField("ContactsAndFaults_ID")) + "' OR ContactsAndFaults_ID = '";
                        break;
                    case "OtherLines":
                        OtherLinesSearch += thisFeature.get_Value(thisFeature.Table.FindField("OtherLines_ID")) + "' OR OtherLines_ID = '";
                        break;
                    case "StationPoints":
                        StationPointsSearch += thisFeature.get_Value(thisFeature.Table.FindField("StationPoints_ID")) + "' OR StationPoints_ID = '";
                        break;
                    case "SamplePoints":
                        SamplePointsSearch += thisFeature.get_Value(thisFeature.Table.FindField("SamplePoints_ID")) + "' OR SamplePoints_ID = '";
                        break;
                    case "OrientationDataPoints":
                        OrientationDataPointsSearch += thisFeature.get_Value(thisFeature.Table.FindField("OrientationDataPoints_ID")) + "' OR OrientationDataPoints_ID = '";
                        break;
                }

                // Iterate the enumeration
                thisFeature = selectionEnum.Next();
            }

            #region "Build Dictionary"
            // Clean up the Where Clauses, create the data access classes, and then add it to the dictionary

            // MapUnitPolys
            if (MapUnitPolysSearch != "MapUnitPolys_ID = '")
            {
                MapUnitPolysSearch = MapUnitPolysSearch.Remove(MapUnitPolysSearch.Length - 23);
                MapUnitPolysAccess MapUnitPolysRecords = new MapUnitPolysAccess(m_theWorkspace);
                MapUnitPolysRecords.AddMapUnitPolys(MapUnitPolysSearch);
                dataAccessClasses.Add("MapUnitPolys", MapUnitPolysRecords);
            }

            // OverlayPolys
            if (OverlayPolysSearch != "OverlayPolys_ID = '")
            {
                OverlayPolysSearch = OverlayPolysSearch.Remove(OverlayPolysSearch.Length - 23);
                OverlayPolysAccess OverlayPolysRecords = new OverlayPolysAccess(m_theWorkspace);
                OverlayPolysRecords.AddOverlayPolys(OverlayPolysSearch);
                dataAccessClasses.Add("OverlayPolys", OverlayPolysRecords);
            }

            // ContactsAndFaults
            if (ContactsAndFaultsSearch != "ContactsAndFaults_ID = '")
            {
                ContactsAndFaultsSearch = ContactsAndFaultsSearch.Remove(ContactsAndFaultsSearch.Length - 28);
                ContactsAndFaultsAccess ContactsAndFaultsRecords = new ContactsAndFaultsAccess(m_theWorkspace);
                ContactsAndFaultsRecords.AddContactsAndFaults(ContactsAndFaultsSearch);
                dataAccessClasses.Add("ContactsAndFaults", ContactsAndFaultsRecords);
            }

            // OtherLines
            if (OtherLinesSearch != "OtherLines_ID = '")
            {
                OtherLinesSearch = OtherLinesSearch.Remove(OtherLinesSearch.Length - 21);
                OtherLinesAccess OtherLinesRecords = new OtherLinesAccess(m_theWorkspace);
                OtherLinesRecords.AddOtherLines(OtherLinesSearch);
                dataAccessClasses.Add("OtherLines", OtherLinesRecords);
            }

            // StationPoints
            if (StationPointsSearch != "StationPoints_ID = '")
            {
                StationPointsSearch = StationPointsSearch.Remove(StationPointsSearch.Length - 24);
                StationPointsAccess StationPointsRecords = new StationPointsAccess(m_theWorkspace);
                StationPointsRecords.AddStationPoints(StationPointsSearch);
                dataAccessClasses.Add("StationPoints", StationPointsRecords);
            }

            // SamplePoints
            if (SamplePointsSearch != "SamplePoints_ID = '")
            {
                SamplePointsSearch = SamplePointsSearch.Remove(SamplePointsSearch.Length - 23);
                SamplePointsAccess SamplePointsRecords = new SamplePointsAccess(m_theWorkspace);
                SamplePointsRecords.AddSamplePoints(SamplePointsSearch);
                dataAccessClasses.Add("SamplePoints", SamplePointsRecords);
            }

            // OrientationDataPoints
            if (OrientationDataPointsSearch != "OrientationDataPoints_ID = '")
            {
                OrientationDataPointsSearch = OrientationDataPointsSearch.Remove(OrientationDataPointsSearch.Length - 32);
                OrientationDataPointsAccess OrientationDataPointsRecords = new OrientationDataPointsAccess(m_theWorkspace);
                OrientationDataPointsRecords.AddOrientationDataPoints(OrientationDataPointsSearch);
                dataAccessClasses.Add("OrientationDataPoints", OrientationDataPointsRecords);
            }

            #endregion

            #endregion

            #region Selected TABLE ROWS
            // Loop through the tables in the map
            IStandaloneTableCollection tableCollection = ArcMap.Document.FocusMap as IStandaloneTableCollection;
            for (int i = 0; i <= tableCollection.StandaloneTableCount - 1; i++)
            {
                // Get one of the tables
                IStandaloneTable thisTable = tableCollection.StandaloneTable[i];
                string tableName = (thisTable.Table as IDataset).Name;

                // Parse the table name in order to strip out unneccessary bits of SDE tables
                ISQLSyntax nameParser = (ISQLSyntax)m_theWorkspace;
                string parsedDbName, parsedOwnerName, parsedTableName;
                nameParser.ParseTableName(tableName, out parsedDbName, out parsedOwnerName, out parsedTableName);

                // Find the selection
                ITableSelection selectedRows = thisTable as ITableSelection;
                ISelectionSet theSelection = selectedRows.SelectionSet;

                // Iterate if there are no selected rows
                if (theSelection.Count == 0) { continue; }

                // Loop through selected rows, build the where clauses up.
                ICursor theCursor;
                theSelection.Search(null, false, out theCursor);

                IRow theRow = theCursor.NextRow();
                while (theRow != null)
                {
                    switch (parsedTableName)
                    {
                        case "Glossary":
                            GlossarySearch += theRow.get_Value(thisTable.Table.FindField("Glossary_ID")) + "' OR Glossary_ID = '";
                            break;
                        case "Notes":
                            NotesSearch += theRow.get_Value(thisTable.Table.FindField("Notes_ID")) + "' OR Notes_ID = '";
                            break;
                        case "RelatedDocuments":
                            RelatedDocumentsSearch += theRow.get_Value(thisTable.Table.FindField("RelatedDocuments_ID")) + "' OR RelatedDocuments_ID = '";
                            break;
                        case "DataSources":
                            DataSourcesSearch += theRow.get_Value(thisTable.Table.FindField("DataSources_ID")) + "' OR DataSources_ID = '";
                            break;
                        case "DescriptionOfMapUnits":
                            DescriptionOfMapUnitsSearch += theRow.get_Value(thisTable.Table.FindField("DescriptionOfMapUnits_ID")) + "' OR DescriptionOfMapUnits_ID = '";
                            break;
                    }

                    // Iterate
                    theRow = theCursor.NextRow();
                }
            }

            #region Build Dictionary
            // Clean up the Where Clauses, create the data access classes, and then add it to the dictionary

            // Glossary
            if (GlossarySearch != "Glossary_ID = '")
            {
                GlossarySearch = GlossarySearch.Remove(GlossarySearch.Length - 19);
                GlossaryAccess GlossaryRecords = new GlossaryAccess(m_theWorkspace);
                GlossaryRecords.AddGlossary(GlossarySearch);
                dataAccessClasses.Add("Glossary", GlossaryRecords);
            }

            // Notes
            if (NotesSearch != "Notes_ID = '")
            {
                NotesSearch = NotesSearch.Remove(NotesSearch.Length - 16);
                NotesAccess NotesRecords = new NotesAccess(m_theWorkspace);
                NotesRecords.AddNotes(NotesSearch);
                dataAccessClasses.Add("Notes", NotesRecords);
            }

            // RelatedDocuments
            if (RelatedDocumentsSearch != "RelatedDocuments_ID = '")
            {
                RelatedDocumentsSearch = RelatedDocumentsSearch.Remove(RelatedDocumentsSearch.Length - 27);
                RelatedDocumentsAccess RelatedDocumentsRecords = new RelatedDocumentsAccess(m_theWorkspace);
                RelatedDocumentsRecords.AddRelatedDocuments(RelatedDocumentsSearch);
                dataAccessClasses.Add("RelatedDocuments", RelatedDocumentsRecords);
            }

            // DataSources
            if (DataSourcesSearch != "DataSources_ID = '")
            {
                DataSourcesSearch = DataSourcesSearch.Remove(DataSourcesSearch.Length - 22);
                DataSourcesAccess DataSourcesRecords = new DataSourcesAccess(m_theWorkspace);
                DataSourcesRecords.AddDataSources(DataSourcesSearch);
                dataAccessClasses.Add("DataSources", DataSourcesRecords);
            }

            // DescriptionOfMapUnits
            if (DescriptionOfMapUnitsSearch != "DescriptionOfMapUnits_ID = '")
            {
                DescriptionOfMapUnitsSearch = DescriptionOfMapUnitsSearch.Remove(DescriptionOfMapUnitsSearch.Length - 32);
                DescriptionOfMapUnitsAccess DescriptionOfMapUnitsRecords = new DescriptionOfMapUnitsAccess(m_theWorkspace);
                DescriptionOfMapUnitsRecords.AddDescriptionOfMapUnits(DescriptionOfMapUnitsSearch);
                dataAccessClasses.Add("DescriptionOfMapUnits", DescriptionOfMapUnitsRecords);
            }

            #endregion

            #endregion

            // Okay! Return the dictionary that has been built
            return dataAccessClasses;
        }
        private void tlsbtnAssignUnit_Click(object sender, EventArgs e)
        {
            // Find the selected DMU Entry
            string dmuID = trvLegendItems.SelectedNode.Name;
            if (dmuID == null) { return; }

            DescriptionOfMapUnitsAccess dmuAccess = new DescriptionOfMapUnitsAccess(m_theWorkspace);
            dmuAccess.AddDescriptionOfMapUnits("DescriptionOfMapUnits_ID = '" + dmuID + "'");
            DescriptionOfMapUnitsAccess.DescriptionOfMapUnit dmuEntry = dmuAccess.DescriptionOfMapUnitsDictionary[dmuID];

            // Get selected polygons
            IFeatureLayer mapUnitPolysLayer = commonFunctions.FindFeatureLayer(m_theWorkspace, "MapUnitPolys");

            // Find out if there are selected features
            IFeatureSelection featureSelection = (IFeatureSelection)mapUnitPolysLayer;
            ISelectionSet theSelection = featureSelection.SelectionSet;

            // Bail if nothing was selected
            if (theSelection.Count == 0) { return; }

            // Pass the selected features into a cursor that we can iterate through
            ICursor theCursor;
            theSelection.Search(null, false, out theCursor);
            int IdFld = theCursor.FindField("MapUnitPolys_ID");

            // Build the Where Clause to get these features by looping through the cursor
            string sqlWhereClause = "MapUnitPolys_ID = '";
            IRow theRow = theCursor.NextRow();
            while (theRow != null)
            {
                sqlWhereClause += theRow.get_Value(IdFld) + "' OR MapUnitPolys_ID = '";
                theRow = theCursor.NextRow();
            }

            System.Runtime.InteropServices.Marshal.ReleaseComObject(theCursor);

            // If we didn't add anything to the where clause, bail
            if (sqlWhereClause == "MapUnitPolys_ID = '") { return; }

            // Cleanup the where clause
            sqlWhereClause = sqlWhereClause.Remove(sqlWhereClause.Length - 23);

            // Get the MapUnitPolys
            MapUnitPolysAccess polysAccess = new MapUnitPolysAccess(m_theWorkspace);
            polysAccess.AddMapUnitPolys(sqlWhereClause);

            //---------------------------------------------------------------------------------
            //---------------------------------------------------------------------------------
            // Data Access Issue: I actually have to pass the dictionary into another object.
            //  If I don't, once the first record is updated, the dictionary is changed.
            //  Then the foreach loop fails, because what it is looping through was adjusted.
            //  Not very happy with this.
            //---------------------------------------------------------------------------------
            //---------------------------------------------------------------------------------

            // Sort using Linq syntax
            var sortedPolys = (
                from entry in polysAccess.MapUnitPolysDictionary
                select entry);

                MapUnitPolysAccess secondPolysAccess = new MapUnitPolysAccess(m_theWorkspace);
            try
            {
                // Cycle through the MapUnitPolys and update the MapUnit and Label  attributes
                foreach (KeyValuePair<string, MapUnitPolysAccess.MapUnitPoly> anEntry in sortedPolys)
                {
                    // Get the MapUnitPoly object
                    secondPolysAccess.AddMapUnitPolys("MapUnitPolys_ID = '" + anEntry.Value.MapUnitPolys_ID + "'");
                    MapUnitPolysAccess.MapUnitPoly aPoly = secondPolysAccess.MapUnitPolysDictionary[anEntry.Value.MapUnitPolys_ID];

                    // Change the appropriate values
                    aPoly.MapUnit = dmuEntry.MapUnit;
                    aPoly.Label = dmuEntry.Label;

                    // Update the Poly
                    secondPolysAccess.UpdateMapUnitPoly(aPoly);
                }
            }
            catch (Exception err) { MessageBox.Show(err.Message); }

            // Save updates
            secondPolysAccess.SaveMapUnitPolys();

            // Update the active view
            ArcMap.Document.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, mapUnitPolysLayer, null);
        }