Dictionary renderer with graphics overlay

View inMAUIWPFUWPWinUIView on GitHubSample viewer app

Create graphics from an XML file with key-value pairs for each graphic, and display the military symbols using a MIL-STD-2525D web style in 2D.

Image of dictionary renderer graphics overlay

Use case

Use a dictionary renderer on a graphics overlay to display more transient data, such as military messages coming through a local tactical network.

How to use the sample

Pan and zoom to explore military symbols on the map.

How it works

  1. Create a new DictionarySymbolStyle using a MIL-STD-2525D dictionary web style.
  2. Create a new DictionaryRenderer from the dictionary symbol style.
  3. Create a new GraphicsOverlay.
  4. Set the dictionary renderer to the graphics overlay.
  5. Parse through the XML and create a graphic for each element.
  6. Use the _wkid key to get the geometry's spatial reference.
  7. Use the _control_points key to get the geometry's shape.
  8. Create a geometry using the shape and spatial reference from above.
  9. Create a Graphic for each attribute, utilizing it's defined geometry.
  10. Add the graphic to the graphics overlay.

Relevant API

  • DictionaryRenderer
  • DictionarySymbolStyle
  • GraphicsOverlay

Offline data

This sample uses the MIL-STD-2525D XML Message File hosted on ArcGIS Online.

About the data

The dictionary symbol style in this sample is constructed from a portal item containing a MIL-STD-2525D symbol dictionary web style. This ArcGIS Web Style is used to build custom applications that incorporate the MIL-STD-2525D symbol dictionary. This style supports a configuration for modeling locations as ordered anchor points or full geometries.

Tags

defense, military, situational awareness, tactical, visualization

Sample Code

DictionaryRendererGraphicsOverlay.xaml.csDictionaryRendererGraphicsOverlay.xaml.csDictionaryRendererGraphicsOverlay.xaml
Use dark colors for code blocksCopy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2019 Esri.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
// language governing permissions and limitations under the License.

using ArcGIS.Samples.Managers;
using Esri.ArcGISRuntime.Geometry;
using Esri.ArcGISRuntime.Mapping;
using Esri.ArcGISRuntime.Symbology;
using Esri.ArcGISRuntime.UI;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Xml.Linq;

namespace ArcGIS.WPF.Samples.DictionaryRendererGraphicsOverlay
{
    [ArcGIS.Samples.Shared.Attributes.Sample(
        name: "Dictionary renderer with graphics overlay",
        category: "GraphicsOverlay",
        description: "Create graphics from an XML file with key-value pairs for each graphic, and display the military symbols using a MIL-STD-2525D web style in 2D.",
        instructions: "Pan and zoom to explore military symbols on the map.",
        tags: new[] { "defense", "military", "situational awareness", "tactical", "visualization" })]
    [ArcGIS.Samples.Shared.Attributes.OfflineData("8776cfc26eed4485a03de6316826384c")]
    public partial class DictionaryRendererGraphicsOverlay
    {
        // Hold a reference to the graphics overlay for easy access.
        private GraphicsOverlay _tacticalMessageOverlay;

        public DictionaryRendererGraphicsOverlay()
        {
            InitializeComponent();
            _ = Initialize();
        }

        private async Task Initialize()
        {
            try
            {
                MyMapView.Map = new Map(BasemapStyle.ArcGISTopographic);

                // Create an overlay for visualizing tactical messages and add it to the map.
                _tacticalMessageOverlay = new GraphicsOverlay();
                MyMapView.GraphicsOverlays.Add(_tacticalMessageOverlay);

                // Prevent graphics from showing up when zoomed too far out.
                _tacticalMessageOverlay.MinScale = 1000000;

                // Create the dictionary symbol style from the Joint Military Symbology MIL-STD-2525D portal item.
                var symbolStyleUri = new Uri("https://www.arcgis.com/home/item.html?id=d815f3bdf6e6452bb8fd153b654c94ca");
                DictionarySymbolStyle dictionarySymbolStyle = await DictionarySymbolStyle.OpenAsync(symbolStyleUri);

                // Find the first configuration setting which has the property name "model", and set its value to "ORDERED ANCHOR POINTS".
                //if (dictionarySymbolStyle?.Configurations?.FirstOrDefault(config => config.Name == "model") is DictionarySymbolStyleConfiguration configuration)
                if (dictionarySymbolStyle?.Configurations?.FirstOrDefault(config => config.Name == "model") is DictionarySymbolStyleConfiguration configuration)
                {
                    configuration.Value = "ORDERED ANCHOR POINTS";
                }

                // Create a new dictionary renderer from the dictionary symbol style to render graphics with symbol dictionary attributes and set it to the graphics overlay renderer.
                _tacticalMessageOverlay.Renderer = new DictionaryRenderer(dictionarySymbolStyle);

                // Parse graphic attributes from an XML file following the mil2525d specification.
                LoadMilitaryMessages();

                // Get the extent of the graphics.
                Envelope graphicExtent = GeometryEngine.CombineExtents(_tacticalMessageOverlay.Graphics.Select(graphic => graphic.Geometry));

                // Zoom to the extent of the graphics.
                await MyMapView.SetViewpointGeometryAsync(graphicExtent, 10);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, ex.GetType().Name, MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LoadMilitaryMessages()
        {
            // Get the path to the messages file.
            string militaryMessagePath = DataManager.GetDataFolder("8776cfc26eed4485a03de6316826384c", "Mil2525DMessages.xml");

            // Load the XML document.
            XElement xmlRoot = XElement.Load(militaryMessagePath);

            // Get all of the messages.
            IEnumerable<XElement> messages = xmlRoot.Descendants("message");

            // Add a graphic for each message.
            foreach (var message in messages)
            {
                Graphic messageGraphic = GraphicFromAttributes(message.Descendants().ToList());
                _tacticalMessageOverlay.Graphics.Add(messageGraphic);
            }
        }

        private Graphic GraphicFromAttributes(List<XElement> graphicAttributes)
        {
            // Get the geometry and the spatial reference from the message elements.
            XElement geometryAttribute = graphicAttributes.First(attr => attr.Name == "_control_points");
            XElement spatialReferenceAttr = graphicAttributes.First(attr => attr.Name == "_wkid");

            // Split the geometry field into a list of points.
            Array pointStrings = geometryAttribute.Value.Split(';');

            // Create a point collection in the correct spatial reference.
            int wkid = Convert.ToInt32(spatialReferenceAttr.Value);
            SpatialReference pointSR = SpatialReference.Create(wkid);
            PointCollection graphicPoints = new PointCollection(pointSR);

            // Add a point for each point in the list.
            foreach (string pointString in pointStrings)
            {
                var coords = pointString.Split(',');
                graphicPoints.Add(Convert.ToDouble(coords[0], CultureInfo.InvariantCulture), Convert.ToDouble(coords[1], CultureInfo.InvariantCulture));
            }

            // Create a multipoint from the point collection.
            Multipoint graphicMultipoint = new Multipoint(graphicPoints);

            // Create the graphic from the multipoint.
            Graphic messageGraphic = new Graphic(graphicMultipoint);

            // Add all of the message's attributes to the graphic (some of these are used for rendering).
            foreach (XElement attr in graphicAttributes)
            {
                messageGraphic.Attributes[attr.Name.ToString()] = attr.Value;
            }

            return messageGraphic;
        }
    }
}

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.