private void RepairWithDataset(IDataLayer2 dataLayer, Moves.GisDataset oldDataset, Moves.GisDataset newDataset, AlertForm alert) { // This routine, can only repair workspace path, and dataset name. // The workspace type and data type must be the same. // This can be checked with the CSV verifier. Violations will be ignored in the CSV loader if (oldDataset.DatasourceType != newDataset.DatasourceType || oldDataset.WorkspaceProgId != newDataset.WorkspaceProgId) { return; } var helper = (IDataSourceHelperLayer) new DataSourceHelper(); if (oldDataset.DatasourceName == newDataset.DatasourceName) { helper.FindAndReplaceWorkspaceNamePath((ILayer)dataLayer, oldDataset.Workspace.Folder, newDataset.Workspace.Folder, false); } else { // I can't find a way to simply change the name of the dataset in a layer. // To set the data source of a layer I need to first open the data source (using the newDataset properties) // I can then use the Name (as IName) of the data source to fix the layer. IDataset dataset = TryOpenDataset(newDataset); if (dataset == null) { alert.Text = @"Error"; alert.msgBox.Text = $"Map Fixer is unable to repair the layer {((ILayer2)dataLayer).Name}. " + "Use the 'Set Data Source button' on the Source tab of the layer properties dialog to " + $"set the data source to {newDataset.Workspace.Folder}\\{newDataset.DatasourceName}"; alert.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd))); return; } helper.ReplaceName((ILayer)dataLayer, dataset.FullName, false); } }
public void FixMap(Moves moves) { var brokenDataSources = GetBrokenDataSources(); // We do not need to do anything if there was nothing to fix if (brokenDataSources.Count == 0) { return; } var alert = new AlertForm(); var selector = new SelectionForm(); var autoFixesApplied = 0; var unFixableLayers = 0; var intentionallyBroken = 0; foreach (var item in brokenDataSources) { var mapIndex = item.Key; foreach (IDataLayer2 dataLayer in item.Value) { var layerName = dataLayer is IDataset dataset ? dataset.Name : ((ILayer2)dataLayer).Name; Moves.GisDataset oldDataset = GetDataset(dataLayer); Moves.Solution? maybeSolution = moves.GetSolution(oldDataset); if (maybeSolution == null) { unFixableLayers += 1; continue; } Moves.Solution solution = maybeSolution.Value; if (solution.NewDataset != null && solution.ReplacementDataset == null && solution.ReplacementLayerFilePath == null && solution.Remarks == null) { // This is the optimal action. // The user is not prompted, since there is no good reason for a user not to click OK. // The user will be warned that layers have been fixed, and they can choose to not save the changes. autoFixesApplied += 1; RepairWithDataset(dataLayer, oldDataset, solution.NewDataset.Value, alert); } else { selector.LayerName = layerName; //selector.GisDataset = oldDataset; selector.Solution = solution; selector.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd))); if (selector.UseLayerFile) { RepairWithLayerFile(mapIndex, dataLayer, selector.LayerFile, selector.KeepBrokenLayer, alert); if (selector.KeepBrokenLayer) { intentionallyBroken += 1; } } else if (selector.UseDataset && selector.Dataset.HasValue) { RepairWithDataset(dataLayer, oldDataset, selector.Dataset.Value, alert); } else { intentionallyBroken += 1; } } } } // Refresh TOC ArcMap.Document.UpdateContents(); //update the TOC ArcMap.Document.ActivatedView.Refresh(); // refresh the view // Print a Summary brokenDataSources = GetBrokenDataSources(); // Some unfixable layers may actually have been corrected by fixing the Mosaic Dataset Layer // Limit unfixable to no more than the actual number of broken layers unFixableLayers = Math.Min(unFixableLayers, brokenDataSources.Count); if (autoFixesApplied > 0 || unFixableLayers > 0 || brokenDataSources.Count > intentionallyBroken) { string msg = ""; if (autoFixesApplied > 0) { msg += $"{autoFixesApplied} broken layers were automatically fixed based on the new locations of known data sources. " + "Close the document without saving if this is not what you want."; } if (autoFixesApplied > 0 && (unFixableLayers > 0 || brokenDataSources.Count > 0)) { msg += "\n\n"; } if (unFixableLayers > 0) { msg += $"{unFixableLayers} broken layers could not be fixed; breakage is not due to changes on the PDS (X drive)."; } if (unFixableLayers < brokenDataSources.Count - intentionallyBroken) { // We know that brokenDataSources.Count must be >= unFixableLayers, therefore some of the fixes need fixing if (unFixableLayers > 0) { msg += "\n\n"; } msg += "Additional fixes are possible and needed. Please save, close and reopen your map."; } alert.Text = @"Map Fixer Summary"; alert.msgBox.Text = msg; alert.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd))); } }
private void RepairWithLayerFile(int mapIndex, IDataLayer2 dataLayer, string newLayerFile, bool keepBrokenLayer, AlertForm alert) { // Add Layer File to ActiveView Snippet: (http://help.arcgis.com/en/sdk/10.0/arcobjects_net/componenthelp/index.html#//004900000050000000) IGxLayer gxLayer = new GxLayer(); IGxFile gxFile = (IGxFile)gxLayer; gxFile.Path = newLayerFile; if (gxLayer.Layer != null) { // AddLayer will add the new layer at the most appropriate point in the TOC. // This is much easier and potentially less confusing than adding at the old data location. ArcMap.Document.Maps.Item[mapIndex].AddLayer(gxLayer.Layer); if (!keepBrokenLayer) { ArcMap.Document.Maps.Item[mapIndex].DeleteLayer((ILayer)dataLayer); } } else { // Notify the user that the LayerFile could not be opened (missing, corrupt, ...) alert.Text = @"Error"; alert.msgBox.Text = $"The layer file '{newLayerFile}' could not be opened."; alert.ShowDialog(new WindowWrapper(new IntPtr(ArcMap.Application.hWnd))); } }