Polygon Label features dont show

1112
11
Jump to solution
08-01-2022 08:48 AM
ofirrosner
New Contributor III

Hello

I'm using this guide
with the example from JsonLabelClass
When i add a polygon and i want to add text to it with PolygonAlwaysHorizontal no text is showing.

But when I'm using any of the line options(e.g LineAboveBefore) it will show my text(not in the optimal way) but something i shown

why the polygon one is not showing and how can i overcome it?

0 Kudos
1 Solution

Accepted Solutions
ThadTilton
Esri Contributor

I think you're just missing the quotes around the guid value: 

WhereClause = $"GUID LIKE '{guid}'"

 

Here's the code that worked for me:

private async void CreatePolyButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    var poly = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polygon, false);
    string guid = Guid.NewGuid().ToString();
    var attr = new Dictionary<string, object>
    {
        { "GUID", guid }
    };
    var graphic = new Graphic(poly, attr);
    _overlay.Graphics.Add(graphic);

    var labelDef = GetGraphicLabelDef(System.Drawing.Color.Firebrick, guid);
    _overlay.LabelDefinitions.Clear();
    _overlay.LabelsEnabled = true;
    _overlay.LabelDefinitions.Add(labelDef);
}

private LabelDefinition GetGraphicLabelDef(System.Drawing.Color color, string guid)
{
    // Create a text symbol for styling the label.
    TextSymbol textSymbol = new TextSymbol
    {
        Size = 12,
        FontFamily = "Arial",
        Color = color,
        HaloColor = Color.White,
        HaloWidth = 2,
    };

    // Create a label expression using an Arcade expression script.
    LabelExpression arcadeLabelExpression = new ArcadeLabelExpression("$feature.GUID");

    // Create a new LabelInfo object and set the relevant properties (including the text symbol).
    var labelInfo = new LabelClassInfo(GeometryType.Polygon)
    {
        LabelPosition = LabelPosition.Static,
        ArcadeExpression = arcadeLabelExpression.Expression,
        MinScale = 0,
        MaxScale = 0,
        LabelPlacement = LabelPlacement.PolygonAlwaysHorizontal,
        Priority = 30,
        RemoveDuplicateLabels = DuplicateLabels.FeatureType,
        StackLabel = true,
        Symbol = textSymbol,
        WhereClause = $"GUID LIKE '{guid}'"
    };

    // Get the raw JSON from the label info object.
    string labelJson = labelInfo.ToJson();

    // Create a new label definition from the JSON string.
    LabelDefinition labelDef = LabelDefinition.FromJson(labelJson);
    return labelDef;
}

View solution in original post

0 Kudos
11 Replies
ThadTilton
Esri Contributor

Hi, I'm sorry to hear the JSON label code isn't working for you. The good news is, as of v100.11, ArcGIS Runtime provides a labeling API to wrap this functionality. If you're able to move to a more recent version, perhaps try using the API to add your labels. You'll find more details in the developer guide here: https://developers.arcgis.com/net/styles-and-data-visualization/add-labels/

0 Kudos
ofirrosner
New Contributor III

Thanks
im using 100.5.0 and sadly we cannot upgrade. but we found workaround

on that, a follow up question
IS there a way to edit label color/font size/font family/etc on runtime.
The LabelDefinition is defined per layer.
For example to change the font-familly:

_layer.LabelDefinitions.Clear();
labelClass.Symbol.Font.Family = _fontfamily

it works fine for 1 or maybe two polygons or screen but with more its starts to get glitchy/dosent work at all

0 Kudos
ThadTilton
Esri Contributor

I think the way you were doing it should work well, simply changing the text symbol properties on the label class. I tested a little and found that code like this worked as expected to change the font family for my labels.

_labelDefinition.TextSymbol.FontFamily = FontFamilyTextBox.Text.Trim();

The "_labelDefinition" variable is one of the label definitions defined for a feature layer. I simply stored it as a member variable so I could refer to it later. I did find that some fonts didn't work (like Segoe UI Emoji, eg) and the labels would just fall back to something like Arial. I also noticed that some fonts would result in a larger label and change which features labels were displayed. One caveat, I was testing using the same JSON label class but with a newer version of runtime (100.14). 

0 Kudos
ofirrosner
New Contributor III

but wont it change the FontFamily(and all the other properties of the TextSymbol) to all  polygons/polylines/etc on the same layer?

if i wasn't clear, i want to control the TextSymbol individually per item in the layer
is that even possible?
Thanks

0 Kudos
ThadTilton
Esri Contributor

It would change it for all labels in the label definition. When you create a label definition, you can use a where clause to restrict which features are included. That allows you to do things like label major cities with a different label than smaller ones, etc.

I don't think that was illustrated in the JSON class example, but it would look something like this (notice the addition of the 'WhereClause').

// Create a new LabelInfo object and set the relevant properties (including the text symbol).
LabelClassInfo labelInfo = new LabelClassInfo()
{
	LabelPosition = "static",
	ArcadeExpression = "return $feature['" + LabelFieldComboBox.SelectedItem + "'];",
	MinScale = 0,
	MaxScale = 0,
	Priority = 30,
	RemoveDuplicateLabels = "featureType",
	StackLabel = true,
	Symbol = textSymbol,
        WhereClause = $"POP2020 > 1000000"
};
// Get the raw JSON from the label info object.
labelJson = labelInfo.GetJson();

// Create a new label definition from the JSON string.
LabelDefinition labelDef = LabelDefinition.FromJson(labelJson);

This will label all features with a POP2020 attribute value greater than one million using the symbol defined. If you change the font or other properties of the symbol, it will only change the labels in this definition. If you need to narrow this down to a single feature, you could use a where clause based on a unique ID and then control that one feature's label.

Your other option would be to add a graphic to display the label for the feature. You can create a point to define where the label should appear, apply the appropriate TextSymbol, and then add it to a GraphicsOverlay in the view (see doc here for more info: https://developers.arcgis.com/net/maps-2d/add-graphics-to-a-map-view/#display-text).

0 Kudos
ofirrosner
New Contributor III

Thanks
But wont i need to create LabelClassInfo for each graphic i have on map?
i mean
if i do  WhereClause = $"Guid =  {Guid}"
so it means that only 1 graphic will we able to abide to this rule
what im currently doing

LabelClass lableClass = GetExtendedLabel(guid)
int random = random.next(10,50);
grahpic.Attributes["GUID"] = random;
labelClass.Symbil.Font.Size = random;
grahpicOverlay.LabelDefinitions.Add(labelClass.ToLabelDefinition)


and GetExtendedLabel is same as your example just i changed

WhereClause = $"POP2020 > 1000000"

To

WhereClause = $"GUID = {GUID}"


which result in no labels shown

0 Kudos
ThadTilton
Esri Contributor

If you have more than just a few graphics, it probably wouldn't make sense to have a different label class for each one. I guess it depends on what your use case is. If you're doing something like showing the selected geoelement with a special label, you can have a dedicated label class for a selected graphic's label and then dynamically set the where clause on the class to include just the one graphic.

But yes, you can also modify the label symbol at run time as well to change font, size, color, etc.

0 Kudos
ofirrosner
New Contributor III

What i am trying to do ,is after i used the sketch editor to create some graphic on the screen, i want to add label for it and let the user update it properties(text, font color, font size, etc)

this is the code i have atm

public void AddOrUpdateLabel(Guid guid, string text)
{
    var graphic = GetGrahpic(guid)
    graphic.attributes[MapConstans.LabelKey] = text;
    graphic.attributes["GUID"] = guid;
    var labelClass = CreateAndGetExtendedLabel(guid)
    int nextInt = rand.next(10,100);//just for testing purpose
    labelClass.Symbol.Font.size = nextInt;
    AddLabelToMap(labelClass)
    
}

public LabelClass CreateAndGetExtendedLabel(Guid guid)
{
    return new Label()
    {
        LabelPlacement = LabelPlacement.Default,
        LabelExpression = $"[{MapConstans.LabelKey}]";
        Priority = 8,
        DeconfictionStrategy = DeconfictionStrategy .Static,
        RemoveDuplicates = RemoveDuplicatesStrategy.None,
        Symbol = new LabelSymbol()
        {
            Color = Color.White,
            HaloColor = Color.Black,
            HaloSize = 1,
            Font = new Font() {Family = "Arial", Size= 12, weight = 
                               Fontweight.Bold},
        },
        Where = $"GUID LIKE {guid}";
}


 public void AddLabelToMap(LabelClass labelClass)
//adds to labelDefention



with the above code no label is shown  but if i remove the Where = $"GUID LIKE {guid}";  the label is shown but for all graphics at the same layer
P.s
Lets say that, for now, i only create new graphics and not update them, need to add some mechanism if the LabelClass already exists

0 Kudos
ThadTilton
Esri Contributor

I think you're just missing the quotes around the guid value: 

WhereClause = $"GUID LIKE '{guid}'"

 

Here's the code that worked for me:

private async void CreatePolyButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
    var poly = await MyMapView.SketchEditor.StartAsync(SketchCreationMode.Polygon, false);
    string guid = Guid.NewGuid().ToString();
    var attr = new Dictionary<string, object>
    {
        { "GUID", guid }
    };
    var graphic = new Graphic(poly, attr);
    _overlay.Graphics.Add(graphic);

    var labelDef = GetGraphicLabelDef(System.Drawing.Color.Firebrick, guid);
    _overlay.LabelDefinitions.Clear();
    _overlay.LabelsEnabled = true;
    _overlay.LabelDefinitions.Add(labelDef);
}

private LabelDefinition GetGraphicLabelDef(System.Drawing.Color color, string guid)
{
    // Create a text symbol for styling the label.
    TextSymbol textSymbol = new TextSymbol
    {
        Size = 12,
        FontFamily = "Arial",
        Color = color,
        HaloColor = Color.White,
        HaloWidth = 2,
    };

    // Create a label expression using an Arcade expression script.
    LabelExpression arcadeLabelExpression = new ArcadeLabelExpression("$feature.GUID");

    // Create a new LabelInfo object and set the relevant properties (including the text symbol).
    var labelInfo = new LabelClassInfo(GeometryType.Polygon)
    {
        LabelPosition = LabelPosition.Static,
        ArcadeExpression = arcadeLabelExpression.Expression,
        MinScale = 0,
        MaxScale = 0,
        LabelPlacement = LabelPlacement.PolygonAlwaysHorizontal,
        Priority = 30,
        RemoveDuplicateLabels = DuplicateLabels.FeatureType,
        StackLabel = true,
        Symbol = textSymbol,
        WhereClause = $"GUID LIKE '{guid}'"
    };

    // Get the raw JSON from the label info object.
    string labelJson = labelInfo.ToJson();

    // Create a new label definition from the JSON string.
    LabelDefinition labelDef = LabelDefinition.FromJson(labelJson);
    return labelDef;
}
0 Kudos