Create a Double Fill Scale Bar

1000
4
Jump to solution
04-23-2018 01:57 PM
TomFlahive
New Contributor III

I am trying to create a Double Fill Scale Bar in the ArcGIS Pro SDK..  I was able to create a default scale bar using the Esri snippets example (Pro Snippets for Layouts) which did not require specifying the type or styling for the scale bar.  But now I am looking to create a scale bar with a double fill format which means I do need to somehow specify the type and style of the scale bar.  I feel like I am getting close with the following code (just the relevant part of the code below), but it crashes ArcGIS Pro:

Task t = QueuedTask.Run(() =>
{
   Coordinate2D coord2D = new Coordinate2D(xCoord, yCoord);
   CIMDoubleFillScaleBar myScaleBar = new CIMDoubleFillScaleBar
   {
      Division = 4 
   }; 
   ScaleBarStyleItem scaleBarStyle = new ScaleBarStyleItem();
   scaleBarStyle.ScaleBar = myScaleBar; 
   LayoutElementFactory.Instance.CreateScaleBar(activeLayout, coord2D, topMapFrame, scaleBarStyle);
 });‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Does anyone know what I might be missing?  I'm not sure if I am using the CIMDoubleFillScaleBar and the ScaleBarStyleItem correctly.  Thanks.

0 Kudos
1 Solution

Accepted Solutions
CharlesMacleod
Esri Regular Contributor

The problem is the style item. CreateScaleBar wants a ScaleBarStyleItem that will come from the project style file. By default this will be "ArcGIS 2D". You can see the available styles (in ArcGIS 2D) for scalebars when you use the "Scale Bar" button on the Insert tab.

Let's first look at listing out the ScaleBarStyleItems from the project style:

   var arcgis_2d = Project.Current.GetItems<StyleProjectItem>().First(si => si.Name == "ArcGIS 2D");
   StringBuilder sb = new StringBuilder();
   await QueuedTask.Run(() =>
   {
     //Imperial Double Alternating Scale Bar
     //Metric Double Alternating Scale Bar
     //or just use empty string to list them all...
     var scaleBarItems = arcgis_2d.SearchScaleBars("Double Alternating Scale Bar");
     foreach (var sbi in scaleBarItems) {
       sb.AppendLine($"{sbi.Name}, {sbi.Category}, {sbi.Key}");
     }
   });
      
   System.Diagnostics.Debug.WriteLine(sb.ToString());

Now let's use one of the Double Alternating Scale Bar styles to create a scale bar:

  var scaleBarStyle = arcgis_2d.SearchScaleBars("Imperial Double Alternating Scale Bar").First();
  Coordinate2D coord = new Coordinate2D(10.0, 7.0);
  MapFrame mf = layout.FindElement("Map Frame") as MapFrame;
  LayoutElementFactory.Instance.CreateScaleBar(layout, coord, mf, scaleBarStyle);‍‍‍‍

View solution in original post

0 Kudos
4 Replies
CharlesMacleod
Esri Regular Contributor

The problem is the style item. CreateScaleBar wants a ScaleBarStyleItem that will come from the project style file. By default this will be "ArcGIS 2D". You can see the available styles (in ArcGIS 2D) for scalebars when you use the "Scale Bar" button on the Insert tab.

Let's first look at listing out the ScaleBarStyleItems from the project style:

   var arcgis_2d = Project.Current.GetItems<StyleProjectItem>().First(si => si.Name == "ArcGIS 2D");
   StringBuilder sb = new StringBuilder();
   await QueuedTask.Run(() =>
   {
     //Imperial Double Alternating Scale Bar
     //Metric Double Alternating Scale Bar
     //or just use empty string to list them all...
     var scaleBarItems = arcgis_2d.SearchScaleBars("Double Alternating Scale Bar");
     foreach (var sbi in scaleBarItems) {
       sb.AppendLine($"{sbi.Name}, {sbi.Category}, {sbi.Key}");
     }
   });
      
   System.Diagnostics.Debug.WriteLine(sb.ToString());

Now let's use one of the Double Alternating Scale Bar styles to create a scale bar:

  var scaleBarStyle = arcgis_2d.SearchScaleBars("Imperial Double Alternating Scale Bar").First();
  Coordinate2D coord = new Coordinate2D(10.0, 7.0);
  MapFrame mf = layout.FindElement("Map Frame") as MapFrame;
  LayoutElementFactory.Instance.CreateScaleBar(layout, coord, mf, scaleBarStyle);‍‍‍‍
0 Kudos
TomFlahive
New Contributor III

Thanks Charles.  This worked for me and I am now able to create a double fill scale bar.  Can I ask one related follow up question.  I would like to change the font and the number of divisions and subdivisions on this scale bar.  I believe I need to use CIMDoubleFillScaleBar and CIMNumberFormat, but am not sure the proper way to go about this.  Would you be able to show some additional code on the proper way to change the divisions and subdivisions to 2, and the font to a different font?  Thank you.

0 Kudos
CharlesMacleod
Esri Regular Contributor

Try this. 

internal class CreateScaleBar : Button
  {
    protected async override void OnClick()
    {

      var arcgis_2d = Project.Current.GetItems<StyleProjectItem>().First(si => si.Name == "ArcGIS 2D");
      var layout = LayoutView.Active.Layout;

      StringBuilder sb = new StringBuilder();
      await QueuedTask.Run(() =>
      {

        var scaleBarStyle = arcgis_2d.SearchScaleBars("Imperial Double Alternating Scale Bar").First();
        Coordinate2D coord = new Coordinate2D(1.5, 0.5);
        MapFrame mf = layout.FindElement("Map Frame") as MapFrame;
        var scalebar = LayoutElementFactory.Instance.CreateScaleBar(layout, coord, mf, scaleBarStyle);
        //customize
        var cimdef = scalebar.GetDefinition() as CIMDoubleFillScaleBar;
        //divisions
        cimdef.Divisions = 3;//1 for the sub-divisions and two others
        cimdef.Subdivisions = 2;
        //text - division labels
        var textCim = SymbolFactory.Instance.ConstructTextSymbol(
          ColorFactory.Instance.BlueRGB, 12, "Verdana", "Regular");
        cimdef.LabelSymbol = textCim.MakeSymbolReference();

        //unit label - "Miles"
        cimdef.UnitLabelSymbol = textCim.MakeSymbolReference();

        //number format (I have no idea what some of these do so feel
        //free to fiddle - I just set everything...)
        cimdef.NumberFormat = new CIMNumericFormat()
        {
          AlignmentOption = esriNumericAlignmentEnum.esriAlignLeft,
          AlignmentWidth = 10,
          RoundingOption = esriRoundingOptionEnum.esriRoundNumberOfDecimals,
          RoundingValue = 1,
          ShowPlusSign = false,
          UseSeparator = true,
          ZeroPad = false
        };

        //with the CIM you ~must~ set the definition back!
        scalebar.SetDefinition(cimdef);

      });
    }
  }
0 Kudos
TomFlahive
New Contributor III

Thank you Charles.  I'll give that a try.

0 Kudos