Add Layouts in Background to Project/Catalog

1325
11
Jump to solution
08-20-2018 06:34 AM
MKa
by
Occasional Contributor III

I want to add some layouts to my project from the code.  I have about 4 different export templates that I plan to use in a project, so if a user wants to export a selected Item, they select export, the code finds the layout from the Project-->Layouts, updates the text/map elements and saves or shows a pdf to the user.

The problem, is that i want to add these 4 Layouts to a users project if they don't exist.  I plan on putting the pagx files in the config.x file, then on loading a project I will add them to the layouts for a project if they don't exist.  But when I do this, it "Auto" opens the layout when I use additem or import item from the Project tools.  I just want them to be added in the background?   This code below adds the items to layout, but it also opens up the layout tabs for each, which i don't want.  

//1. See if the layouts have been imported to this Project
//Reference all the layout project items
IEnumerable<LayoutProjectItem> layouts = Project.Current.GetItems<LayoutProjectItem>();

//Or reference a specific layout project item by name
LayoutProjectItem layoutItem = Project.Current.GetItems<LayoutProjectItem>().FirstOrDefault(item => item.Name.Equals("CurrentFieldMapHybrid"));

//*************************
//*************************
//THIS BELOW ADDS THE LAYOUT TO THE CATALOG, BUT OPENS UP THE LAYOUT TABS.  I JUST WANT THEM ADDED TO THE LAYOUT CATALOG.  BOTH AddItem AND ImportItem do this
//*************************
//*************************
                //If the layout is null, then import them
                if (layoutItem == null)
                {
                    #region Add new Layout if it doesn't exist

                    await QueuedTask.Run(() =>
                    {
                        //IProjectItem pagx = ItemFactory.Instance.Create(@"xxxxx\CurrentFieldMapHybrid.pagx") as IProjectItem;
                        //Project.Current.AddItem(pagx);

                        IProjectMultiItem pagx = ItemFactory.Instance.Create(@"xxxxx\CurrentFieldMapHybrid.pagx") as IProjectMultiItem;
                        Project.Current.ImportItem(pagx);
                    });

                    #endregion
                }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
Tags (1)
0 Kudos
1 Solution

Accepted Solutions
JeffBarrette
Esri Regular Contributor

2.3 isn't planned for release until the start of 2019.

Jeff

View solution in original post

11 Replies
JeffBarrette
Esri Regular Contributor

Thank you for your feedback.  We are looking into the request and are considering this for a future release.

Jeff

0 Kudos
MKa
by
Occasional Contributor III

Can you think of any type of work around for this?  I don't want the templates or layouts to open at all.  But if they do, i want to have that layout tab close automatically, or when i add the LayoutProjectItem, I quickly close it.  I think after the first time, when it is already in the project I can reference it, but I want to add them all for a project and then close them all.  Then they can all be referenced without opening them.

0 Kudos
MKa
by
Occasional Contributor III

My work around it to add the LayoutProjectItem to the Project if it doesn't already exist, and then close that pane immediatly afterwards.  I don't want the users to see my Layout template.  I then proceed to edit the Elements on that layout page and export the layout to a pdf.  This way a user will never see the layout.  I do need to add the pagx file to the configx file and reference it, but that shouldn't be too difficult.

ProApp.Panes.CloseLayoutPanes(LayoutURI);

//1. See if the layouts have been imported to this Project
//Reference all the layout project items
IEnumerable<LayoutProjectItem> layouts = Project.Current.GetItems<LayoutProjectItem>();

//Or reference a specific layout project item by name
LayoutProjectItem layoutItem = Project.Current.GetItems<LayoutProjectItem>().FirstOrDefault(item => item.Name.Equals("xMap"));

string LayoutURI = "";
//If the layout is null, then import them
if (layoutItem == null)
{ 

await QueuedTask.Run(() =>
{                        
   //Get the layout item from the config file
   IProjectItem pagx = ItemFactory.Instance.Create(@"C:\Users\xxx\Documents\xMap.pagx") as IProjectItem;
   Project.Current.AddItem(pagx);

   layoutItem = Project.Current.GetItems<LayoutProjectItem>().FirstOrDefault(item => item.Name.Equals("XMap"));

   //Get the layout URI so we can auto close it
   Layout li = layoutItem.GetLayout();
   LayoutURI = li.URI;
   });   
}

//Close the layout pane, we don't want to see it
if (!string.IsNullOrEmpty(LayoutURI))
{
   ProApp.Panes.CloseLayoutPanes(LayoutURI);
}

//Get a Layout Element Text and update it
if (layoutItem != null)
{
   await QueuedTask.Run(() =>
   {
      // Reference and load the layout associated with the layout item
      Layout layout = layoutItem.GetLayout();
      if (layout != null)
      {
         //Find a single specific element
            TextElement rect = layout.FindElement("XElementID") as TextElement;
            rect.SetTextProperties(new TextProperties("TestRename", 
            rect.TextProperties.Font, rect.TextProperties.FontSize, 
            rect.TextProperties.FontStyle));
      }
   });
}


//Export the Layout Element
if (layoutItem != null)
{
   // Create the log file and write the current Folder-Connection's to it
   SaveItemDialog saveDialog = new SaveItemDialog();
   saveDialog.Title = "Export the current selected map series item";
   saveDialog.OverwritePrompt = true;
   saveDialog.DefaultExt = "pdf";

   // If the save dialog was not dismissed, create the file
   if (saveDialog.ShowDialog() == true)
   {
      await QueuedTask.Run(() =>
      {
         Layout testlayout = layoutItem.GetLayout();
                            
         PDFFormat PDF = new PDFFormat()
         {
            Resolution = 300,
            OutputFileName = saveDialog.FilePath
         };

         if (PDF.ValidateOutputFilePath())
         {
            testlayout.Export(PDF);                            
         }
      });
   }
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
JeffBarrette
Esri Regular Contributor

Are the layout names hardcoded?  Can you search for a layout pane and close it?

ProApp.Panes.CloseLayoutPanes(layout.URI);

At 2.3 we are adding a new event called LayoutAddedEvent which could be useful in this case.

Jeff

0 Kudos
JeffBarrette
Esri Regular Contributor

Oops - didn't realize I was replying to a second response from you (with the same work around).

0 Kudos
MKa
by
Occasional Contributor III

No that i have that reference to the correct LayoutProjectItem, I am having trouble moving the mapFrame from the mapview.  I seem to continue to get the same map location in my map frame.  I want to move the from pragmatically according to some lat/long or x/y that i send the function.  But when i change the camera X or Y when debugging in the below code, the camera stays in the same spot in my resulting layout print out.

//Get a Layout Element Text and update its values
                if (layoutItem != null)
                {
                    await QueuedTask.Run(() =>
                    {
                        // Reference and load the layout associated with the layout item
                        Layout layout = layoutItem.GetLayout();
                        if (layout != null)
                        {
                            IEnumerable<Element> LayoutElements = layout.Elements;

                            //Find a single specific element
                            TextElement rect = layout.FindElement("Text ID") as TextElement;
                            rect.SetTextProperties(new TextProperties("Test1Mat", rect.TextProperties.Font, rect.TextProperties.FontSize, rect.TextProperties.FontStyle));

//Change Position of the Map Frame elements focus
                            Camera newPosition = new Camera();
                            newPosition.X = MapView.Active.Camera.X;
                            newPosition.Y = MapView.Active.Camera.Y;


                            MapFrame mapFrame = layout.FindElement("MapLayer") as MapFrame;
                            mapFrame.SetMap(MapView.Active.Map);

//I CHANGE the newPosition X and Y below for different printouts, but they all seem to be focused on the same spot of my Active Map
                            mapFrame.SetCamera(newPosition);
                        }
                    });
                }
0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi M,

 I think that your Camera is not properly initialized.  A Camera requires more than just X and Y.  Try to initialize your camera like this 

var newPosition = MapView.Active.Camera;
MKa
by
Occasional Contributor III

Yes.  I was initializing it wrong.  I am able to set my camera to focus on my items centroid (lat/long) with this code.  I had to convert the lat long to x/y.  But it works quite well

//Get the Camera Position of the Item to Print                            
Camera CurrentApplicationCameraPosition = MapView.Active.Camera;

if (exportItemCentroid.SpatialReference.Wkid != CurrentApplicationCameraPosition.SpatialReference.Wkid)
{
   var transformation = 
   ProjectionTransformation.Create(exportItemCentroid.SpatialReference, 
   CurrentApplicationCameraPosition.SpatialReference);
   exportItemCentroid= GeometryEngine.Instance.ProjectEx(exportItemCentroid, transformation) as MapPoint;
}
CurrentApplicationCameraPosition.X = exportItemCentroid.X;
CurrentApplicationCameraPosition.Y = exportItemCentroid.Y;

MapFrame mapFrame = layout.FindElement("MapLayer") as MapFrame;
mapFrame.SetMap(MapView.Active.Map);
mapFrame.SetCamera(CurrentApplicationCameraPosition);
0 Kudos
JeffBarrette
Esri Regular Contributor

The original request to be able to import a pagx without the view opening in the application has been addressed in Pro 2.3 by adding an additional Boolean to the ImportItem method.

IProjectMultiItem pagx = ItemFactory.Instance.Create(@"C:\Active\Layout\SDK\2.3\ImportItemTest.pagx") as IProjectMultiItem;
await QueuedTask.Run(() =>
{
    Project.Current.ImportItem(pagx, false); //Layout view does NOT open (but is added to catalog pane)
    Project.Current.ImportItem(pagx, true); //Layout1 does open (and is added to catalog pane)
});

Jeff

0 Kudos