Labeling

Looking at a bunch of points, a polyline of polygons on the map provides the location of the content, but it doesn't provide enough context about these geometries, even if they have beautiful symbology. Sometimes, it's necessary to label the features with text. Labeling is a cartographic term that means placing text on or near a feature in order to present contextual information to the user. It's possible to use a TextSymbol class and iterate over every feature or graphic, but that would be slow. Fortunately, ArcGIS Runtime comes with a labeling engine that allows you to label each feature or graphic with text in an efficient manner. In fact, with a little code you can label FeatureLayer with hundreds and thousands of features. It also possible to label a GraphicsLayer or GraphicOverlay class.

To label a layer, there are few classes in Esri.ArcGISRuntime.Layers that we need to become familiar with, so let's discuss them, and then see some examples of how to label and the options that we have. See here:

Labeling

The LabelProperties class allows you to enable labeling on a layer. Just set IsEnabled to True. The FeatureLayer, GraphicsLayer, and GraphicOverlay classes have a property named Labeling, which is where you set the LabelProperties class to.

When you set up labeling, you do so with AttributeLabelClass. But you can set up labeling with multiple fields in a FeatureLayer class, for example. To accomplish this, you would create a collection of AttributeLabelClass, and then add them to a AttributeLabelClassCollection class. Once you have the AttributeLabelClassCollection class filled with AttributeLabelClass, you can then apply it to a LabelProperties class, which is then set to the Labeling property of the layer. Here is an example of setting up labeling with a dynamic map service:

<esri:FeatureLayer ID="Cities" >
    <esri:ServiceFeatureTable ServiceUri="http://sampleserver5.arcgisonline.com/arcgis/rest/services/USA/MapServer/0"/>
    <esri:FeatureLayer.Labeling>
        <esri:LabelProperties IsEnabled="True">
            <esri:AttributeLabelClass WhereClause="capital = 'N'"  
                TextExpression="[areaname]" 
            LabelPlacement="PointAboveCenter">
                <esri:TextSymbol Color="OldLace">
                    <esri:SymbolFont FontFamily="Segoe" FontSize="14" 
                    FontWeight="Bold"/>
                </esri:TextSymbol>
            </esri:AttributeLabelClass>
            <esri:AttributeLabelClass WhereClause="capital = 'Y'" 
                TextExpression="[areaname]" 
            LabelPlacement="PointAboveCenter">
                <esri:TextSymbol Color="white">
                    <esri:SymbolFont FontFamily="Segoe" FontSize="18" 
                    FontWeight="Bold"/>
                </esri:TextSymbol>
            </esri:AttributeLabelClass>
        </esri:LabelProperties>
    </esri:FeatureLayer.Labeling>
</esri:FeatureLayer>

And here is an example using code:

// Create a new Uri that points to a FeatureLayer.
System.Uri myUri = new System.Uri("http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer/1");

// Create a new ServiceFeatureTable and set it's ServiceUri and Where 
// clause Properties.
ServiceFeatureTable serviceFeatureTable = new ServiceFeatureTable();
serviceFeatureTable.ServiceUri = myUri.ToString();

// Returns all the fields in the FeatureLayer.
// NOTE: If the Attribute Field that needs to be labeled via the 
// AttributeLabelClass.TextExpression is not returned, then no 
// labeling will occur.
serviceFeatureTable.OutFields = Esri.ArcGISRuntime.Tasks.Query.OutFields.All;

// Create a new instance of an FeatureLayer and set it's Id and FeatureTable Properties.
FeatureLayer featureLayer = new FeatureLayer();
featureLayer.ID = "Highways";
featureLayer.FeatureTable = serviceFeatureTable;

// Define a SimpleLineSymbol for the highways.
SimpleLineSymbol simpleLineSymbol = new SimpleLineSymbol();
simpleLineSymbol.Color = System.Windows.Media.Colors.Black;
simpleLineSymbol.Style = SimpleLineStyle.Solid;
simpleLineSymbol.Width = 1;

// Create a SimpleRenderer to hold the SimpleLineSymbol.
SimpleRenderer simpleRenderer = new SimpleRenderer();
simpleRenderer.Symbol = simpleLineSymbol;

// Apply the SimpleRenderer to the FeatureLayer.
featureLayer.Renderer = simpleRenderer;

// Add the FeatureLayer to the Map.
MyMapView.Map.Layers.Add(featureLayer);

// ------------------------------------------------------------
// Creating and adding the Labeling option to the FeatureLayer.
// ------------------------------------------------------------

// Create an AttributeLabelClass. This contains the meat of the 
// instructions for doing labeling. 
AttributeLabelClass attributeLabelClass = new AttributeLabelClass();
attributeLabelClass.DuplicateLabels = 
DuplicateLabels.RemoveWithinLabelClass;
attributeLabelClass.IsVisible = true;
attributeLabelClass.IsWordWrapEnabled = false;
attributeLabelClass.LabelPlacement = LabelPlacement.LineAboveAlong;
attributeLabelClass.LabelPosition = 
LabelPosition.FixedPositionOrRemove;
attributeLabelClass.LabelPriority = LabelPriority.Medium;
attributeLabelClass.MaxScale = 0;
attributeLabelClass.MinScale = 0;
attributeLabelClass.TextExpression = """ + "I - " + """ + " CONCAT [rte_num1]";
attributeLabelClass.WhereClause = "[rte_num1] <> ' '";
attributeLabelClass.WordWrapLength = 999;

// Create a new TextSymbol to define the appearance of the text that 
// is displayed.
TextSymbol textSymbol = new TextSymbol();
textSymbol.Color = System.Windows.Media.Colors.Black; 
textSymbol.BorderLineColor = System.Windows.Media.Colors.Yellow; 
textSymbol.BorderLineSize = 3; 

// Create a new SymbolFont to define the appearance of the text that 
// is displayed.
SymbolFont mySymbolFont = new SymbolFont();
mySymbolFont.FontFamily = "Verdana"; 
mySymbolFont.FontSize = 12; 
mySymbolFont.FontStyle = SymbolFontStyle.Normal; 
mySymbolFont.TextDecoration = SymbolTextDecoration.None; 
mySymbolFont.FontWeight = SymbolFontWeight.Bold; 
textSymbol.Font = mySymbolFont; 

// Apply the TextSymbol to the AttributeLabelClass.Symbol Property.
// IMPORTANT: This value must be provided or else no labeling will 
// occur! 
attributeLabelClass.Symbol = textSymbol;

// Create a new AttributeLabelClassCollection to hold one or more 
// AttributeLabelClass'es.
AttributeLabelClassCollection attributeLabelClassCollection = new AttributeLabelClassCollection();
attributeLabelClassCollection.Add(attributeLabelClass);

// Create a new LabelProperties to hold the 
// AttributeLabelClassCollection. Make sure it is enabled (i.e. 
// Visible).
LabelProperties labelProperties = new LabelProperties();
labelProperties.IsEnabled = true;
labelProperties.LabelClasses = attributeLabelClassCollection;

// Apply the LabelProperties to the FeatureLayer.Labeling Property.
featureLayer.Labeling = labelProperties;

// Enable labeling on the GraphicsLayer as well.
featureLayer.Labeling.IsEnabled = true;

There are several items of interest that need further explanation.

The DuplicateLabels class provides an enumeration that allows you to specify whether to preserve duplicates (PreserveDuplicates), remove duplicates within the label class (RemoveWithinLabelClass), remove a geometry type from all layers (RemoveByGeometryTypeFromAllLayers), and lastly, you can remove all duplicates from all layers (RemoveAllDuplicatesFromAllLayers). The ability to remove duplicates is very important when working with polylines such as roads. If a road is composed of multiple polylines, the option to remove duplicates can reduce the labeling clutter, which improves performance. See here:

Labeling

Option to remove duplicates reduces the labeling clutter

The LabelPlacement class provides you with the ability to control how the label is placed around points, polylines, or polygons. The LabelPlacement class is composed of the following three parts:

  • The geometry type must match the type of LabelPlacement. For example, PointAboveCenter goes with point geometry. On the other hand, LineAboveBefore goes with polyline geometry.
  • For the vertical position, we use Above, Below, or Center.
  • For the horizontal position, we use Center, Left, Right (Point), Before, Start, Along, End, After (Line).

Some examples of LabelPlacement are PointAboveCenter, PointAboveRight, LineAboveAlong, LineAboveStart, PolygonAlwaysHorizontal, and so on. This last option, PolygonAlwaysHorizontal, deserves a special note. When the labeling engine tries to label a polygon, it will attempt to place the label relative to the first point in the polygon. If you use PolygonAlwaysHorizontal, it will use the polygon's center of mass.

The LabelPosition property determines the label's positioning behavior. The labeling algorithm attempts to place as many labels as possible, based on the properties specified. If you set LabelPosition to FixedPositionOrRemove as shown in the preceding code, this option will result in more labels being produced but will also reduce performance. There are two other options: FixedPositionWithOverlaps, which will force all labels to be placed while keeping overlapping labels, and RepositionOrRemove, which will attempt to reposition or remove labels that can't be repositioned.

The LabelPriority enumeration determines which label AttributeLabelClass has higher priority. If two or more AttributeLabelClass instances are defined, the one with the highest priority will be displayed with higher priority.

The TextExpression property allows you to define how the label will appear along the feature. In this code, the I letter is placed before the route number (rte_num1), along with a dash. Also, note that the field name (rte_num1) has brackets around it. This is how you specify a field name from the feature service in this case. This works the same for any kind of FeatureLayer. Without specifying the TextExpression property, labeling will not occur. Lastly, note that the CONCAT keyword is used to concatenate the literals with the field values.

The WhereClause expression allows you to limit the features that are labeled using a SQL-like expression. In the preceding example code, any route that has some text is labeled. If you want to return all features, use WhereClause such as '1=1' or 'True='True'. Both of these expressions are true. Also, it's important that you know the data type and you need to make sure, as in the preceding example, the fields you are using in WhereClause are returned via ServiceFeatureTable.OutFields. Otherwise, WhereClause won't know the fields to use when searching.

Finally, you can set the Symbol property of the text using TextSymbol and the minimum and maximum scale at which the labels are drawn. It is always recommended to set the minimum and maximum scale to improve the performance of the labeling engine.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.37.126