How to programatically create a new Layout, Open Layout Pane and Switch to Layout View in ArcGIS Pro SDK?
The creation of layouts and layout elements is coming at 2.1. Currently you can only reference existing layouts.
Here is a snippet to create a new, simple layout:
//Create a new layout project item layout in the projectLayout newLayout = await QueuedTask.Run<Layout>(() => { newLayout = LayoutFactory.Instance.CreateLayout(8.5, 11, LinearUnit.Inches); newLayout.SetName("New 8.5x11 Layout"); return newLayout; });//Open new layout on the GUI threadProApp.Panes.CreateLayoutPane(newLayout);
Another example on managing layout views
//A layout view may exist but it may not be active//Iterate through each pane in the application and check to see if the layout is already open and if so, activate itforeach (var pane in ProApp.Panes) { var layoutPane = pane as ILayoutPane; if (layoutPane == null) //if not a layout view, continue to the next pane continue; if (layoutPane.LayoutView.Layout == lyt) //if there is a match, activate the view { (layoutPane as Pane).Activate(); return; } }
There will be many more layout pro snippets addressing these new capabilities when 2.1 is released.
Jeff
Hi Jeff,
Finally, I found a way to open new Layout Programatically in 2.0 SDK too.
var wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_projectContainer_NewLayout");var wcommand = wrapper as ICommand;if (wcommand == null)return;
if (wcommand.CanExecute(null))wcommand.Execute(null);
Once the Layout is opened
LayoutProjectItem layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>();
Then we can do whatever we want to on the Layout.
Hello Suryakant,
I'm really glad you found a work-around for what you need at 2.0 but I'm curious if it really solves the issue. It looks like you found a way to execute the existing New Layout command but how are you adding new elements to it? At 2.1, not only will you be able to create layouts, open them in panes, but you will be able to create all layout element types. Have you found a way to do that too?
Yes, it solved my purpose. Though I had to do some tricks and workarounds.
So, I added 3 elements programatically after I created new Layout as described above. Those elements were MapFrame, North Arrow and Scale Bar. But, I believe similar thing can be done for other elements too.
To create a Map Frame I used following :
wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_newMapFrameButton"); wcommand = wrapper as ICommand; if (wcommand == null) return;
if (wcommand.CanExecute(null)) wcommand.Execute(null);
Then to set its property or zoom level:
LayoutProjectItem layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>(); if (layoutItem != null) { await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { Layout layout = layoutItem.GetLayout(); if (layout == null) return;
MapFrame mf = layout.Elements.FirstOrDefault(item => item.Name.Equals("Map Frame")) as MapFrame; while (mf == null) //actually in large projects Loading map frames takes some time so this is just waiting for it to happen { Task.Delay(TimeSpan.FromSeconds(1)); mf = layout.Elements.FirstOrDefault(item => item.Name.Equals("Map Frame")) as MapFrame; }
mf.SetCamera(camera); //camera is where ever I want to focus/zoom
});
}
For Scale Bar:
await Task.Delay(TimeSpan.FromSeconds(6)); wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_newScaleBarButton"); wcommand = wrapper as ICommand; if (wcommand == null) return;
For North Arrow:
wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_newNorthArrowButton"); wcommand = wrapper as ICommand; if (wcommand == null) return;
In the same manner as for MapFrame :
NorthArrow northArrow = layout.Elements.FirstOrDefault(item => item.Name.Equals("North Arrow")) as NorthArrow; ScaleBar scaleBar = layout.Elements.FirstOrDefault(item => item.Name.Equals("Scale Bar")) as ScaleBar;
Once I got these objects I played with it and set what wanted.
Roughly, my test code looks like following as a whole. Its not optimized and organized yet as it was just for testing but yes it works.
Camera camera = MapView.Active.Camera; int count = ArcGIS.Desktop.Framework.FrameworkApplication.Panes.Find("esri_layouts_layoutPane").Count; var wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_projectContainer_NewLayout"); var wcommand = wrapper as ICommand; if (wcommand == null) return;
while (ArcGIS.Desktop.Framework.FrameworkApplication.Panes.Find("esri_layouts_layoutPane").Count == count) { await Task.Delay(TimeSpan.FromSeconds(3)); }
if (wcommand.CanExecute(null)) wcommand.Execute(null); await Task.Delay(TimeSpan.FromSeconds(1));
LayoutProjectItem layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>(); if (layoutItem != null) { await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { // Reference and load the layout associated with the layout item Layout layout = layoutItem.GetLayout(); if (layout == null) return;
// Reference a mapframe by name MapFrame mf = layout.Elements.FirstOrDefault(item => item.Name.Equals("Map Frame")) as MapFrame; while (mf == null) { Task.Delay(TimeSpan.FromSeconds(1)); mf = layout.Elements.FirstOrDefault(item => item.Name.Equals("Map Frame")) as MapFrame; }
mf.SetCamera(camera);
}); }
if (wcommand.CanExecute(null)) wcommand.Execute(null); layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>();
await Task.Delay(TimeSpan.FromSeconds(6)); wrapper = FrameworkApplication.GetPlugInWrapper("esri_layouts_newNorthArrowButton"); wcommand = wrapper as ICommand; if (wcommand == null) return;
if (wcommand.CanExecute(null)) wcommand.Execute(null); await Task.Delay(TimeSpan.FromSeconds(6)); layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>(); await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { while (layoutItem.GetLayout().Elements.Count() != 3) { Task.Delay(TimeSpan.FromSeconds(1)); layoutItem = Project.Current.GetItems<LayoutProjectItem>().LastOrDefault<LayoutProjectItem>(); } });
await ArcGIS.Desktop.Framework.Threading.Tasks.QueuedTask.Run(() => { // Reference and load the layout associated with the layout item Layout layout = layoutItem.GetLayout(); if (layout == null) return;
// Reference a mapframe by name NorthArrow northArrow = layout.Elements.FirstOrDefault(item => item.Name.Equals("North Arrow")) as NorthArrow; ScaleBar scaleBar = layout.Elements.FirstOrDefault(item => item.Name.Equals("Scale Bar")) as ScaleBar; northArrow.IsVisible = true; northArrow.SetWidth(5); northArrow.SetX(northArrow.GetX() - 1.30); northArrow.SetY(northArrow.GetY() + 1.70);
scaleBar.IsVisible = true; scaleBar.SetWidth(5); scaleBar.SetX(scaleBar.GetX() + 1.30); scaleBar.SetY(scaleBar.GetY() + 2);
Regards,
Surya
Angemeldete Mitglieder können Beiträge verfassen, Updates folgen und mehr. Neu hier? Registriere ein kostenloses Konto.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.