Select to view content in your preferred language

PrintTask With Text Graphics Containing Custom Attributes Error Workaround

2722
1
05-24-2013 03:10 PM
ChrisSaylor
Emerging Contributor
It's been discussed that attempting to print a map where the extent contains text graphics with custom attributes will fail, usually with an error like "Field '<Field Name>' not part of schema for this feature collection".  This isn't a remotely elegant solution whatsoever, but I wanted to pass on what I did to hack around this limitation in case anyone else was facing it.  The gist of it is to clear out the custom attributes from the text symbols before the print starts, and to replace them after the print is completed, using the geometry of the graphics as a unique key (of course assuming all graphics will have at least a slightly different point geometry).

Dictionary<GraphicsLayer, Dictionary<ESRI.ArcGIS.Client.Geometry.MapPoint, Dictionary<string, object>>> textSymbolAttributes = null;

In the method that starts the print task:

LayerCollection lc = MapObject.Layers;
for (int x = 0; x < lc.Count; x++)
{
if (lc is GraphicsLayer)
{
GraphicsLayer gl = (GraphicsLayer)lc;
if (gl.Graphics.Count > 0)
{
//for whatever reason text symbols will not print if they have custom attributes
//there's no completely foolproof way to strip out the attributes now and replace them later
//but it's safe to assume that the geometry will always be slightly different
foreach (Graphic g in gl.Graphics)
{
if (g.Symbol is TextSymbol)
{
if (textSymbolAttributes == null) textSymbolAttributes = new Dictionary<GraphicsLayer, Dictionary<MapPoint, Dictionary<string, object>>>();
if (!textSymbolAttributes.ContainsKey(gl)) textSymbolAttributes.Add(gl, new Dictionary<MapPoint, Dictionary<string, object>>());

Dictionary<string, object> copyDict = new Dictionary<string,object>();
foreach(var dictEntry in g.Attributes) copyDict.Add(dictEntry.Key, dictEntry.Value);
textSymbolAttributes[gl].Add(g.Geometry as MapPoint, copyDict);                  
g.Attributes.Clear();
}
}
}
}
}

After the print job has completed, replace the custom attributes.  Because we don't have any real unique ID to use as a key, I'm going under the assumption that no two graphics will have the exact same point location.

In the PrintCompleted method:

LayerCollection lc = MapObject.Layers;
for (int x = 0; x < lc.Count; x++)
{
if (lc is GraphicsLayer)
{
GraphicsLayer gl = (GraphicsLayer)lc;

//check to see if the current graphics layer is contained in the dictionary
if (textSymbolAttributes != null && textSymbolAttributes.ContainsKey(gl))
{
foreach (Graphic g in gl.Graphics)
{
//only look at text symboles
if (g.Symbol is TextSymbol)
{
MapPoint mp = (MapPoint)g.Geometry;
foreach (var kvp in textSymbolAttributes[gl])
{
//assuming no two text symbols within the same graphics layer wont have identical geometry, we can replace our attributes now that the print is over
if (mp.X == kvp.Key.X & mp.Y == kvp.Key.Y)
{
foreach (var kvp2 in kvp.Value)
{
g.Attributes.Add(kvp2.Key, kvp2.Value);
}
}
}
}
}
}
}
}
0 Kudos
1 Reply
dmacq
by
Occasional Contributor
Thanks for this, Chris. This allows me to print text without an error.

However, stripping the attributes also strips my font settings and text since my symbol is driven by the text graphic's attributes.  Are there any plans to fix this bug, or does somebody have another workaround? 

I'm holding off creating a new symbol for each text graphic, but I think that my be my only solution.
0 Kudos