Archive for Miscellaneous Debris

ArcGIS–Getting the Legend Labels out

Working with ESRI’s ArcGIS package, especially the WPF API, can be confusing. There’s the REST API, the SOAP APIs, and the WPF classes themselves, which expose some web service calls and information, but not everything. With all that, it can be hard to find specific features between the different options. Some functionality is handed to you on a silver platter, while some is maddeningly hard to implement.

Today, for instance, I was working on adding a Legend control to my map-based WPF application, to explain the different symbols that can appear on the map.

This is how the legend looks on ESRI’s own map-editing tools:

 

but this is how it looks when I used the Legend control, supplied out of the box by ESRI:

 

Very pretty, but unfortunately missing the option to display the name of the fields that make up the symbology.

Luckily, the WPF controls have a lot of templating/extensibility points, to allow you to specify the layout of each field:

   1: <esri:Legend>

   2:     <esri:Legend.MapLayerTemplate>

   3:         <DataTemplate>

   4:              <TextBlock Text="{Binding Layer.ID}"/>

   5:         </DataTemplate> 

   6:     </esri:Legend.MapLayerTemplate>

   7: </esri:Legend>

but that only replicates the same built in behavior. I could now add any additional fields I liked, but unfortunately, I couldn’t find them as part of the Layer, GraphicsLayer or FeatureLayer definitions. This is the part where ESRI’s lack of organization is noticeable, since I can see this data easily when accessing the ArcGis Server’s web-interface, but I had no idea how to find it as part of the built-in class. Is it a part of Layer? Of LayerInfo? Of the LayerDefinition class that exists only in the SOAP service?

As it turns out, neither. Since these fields are used by the symbol renderer to determine which symbol to draw, they’re actually a part of the layer’s Renderer. Since I already had a MyFeatureLayer class derived from FeatureLayer that added extra functionality, I could just add this property to it:

   1: public string LegendFields

   2: {

   3:     get

   4:     {

   5:         if (this.Renderer is UniqueValueRenderer)

   6:         {

   7:             return (this.Renderer as UniqueValueRenderer).Field;

   8:         }

   9:         else if (this.Renderer is UniqueValueMultipleFieldsRenderer)

  10:         {

  11:             var renderer = this.Renderer as UniqueValueMultipleFieldsRenderer;

  12:             return string.Join(renderer.FieldDelimiter, renderer.Fields);

  13:         }

  14:         else return null;

  15: }

For my scenario, all of my layers used symbology derived from a single field or, as in the examples above, from several of them. The renderer even kindly supplied me with the comma to separate the fields with. Now it was a simple matter to get the Legend control in line – assuming that it was bound to a collection of MyFeatureLayer:

   1: <esri:Legend>

   2:     <esri:Legend.MapLayerTemplate>

   3:         <DataTemplate>

   4:             <StackPanel>

   5:                 <TextBlock Text="{Binding Layer.ID}"/>

   6:                 <TextBlock Text="{Binding Layer.LegendFields}" Margin="10,0,0,0" TextStyle="Italic"/>

   7:             </StackPanel>

   8:         </DataTemplate>

   9:     </esri:Legend.MapLayerTemplate>

  10: </esri:Legend>

and get the look I wanted – the list of fields below the layer name, indented.

The Case of the Expected Unexpected Exception

“NUnit is being problematic again”, they told me when I came to visit the project. “When running unattended it’s not catching assertions properly and the test is coming up green, but when stepping through in the debugger, it works fine.”. It’s nice, when getting a passing test is acknowledged as a bad thing, at least when you don’t expect it to be. In this case, though, the fault wasn’t really with NUnit.

  1: [Test]
  2: [ExpectedException]
  3: public void DoTheTest()
  4: {
  5:     _myComponent.RunMethod();
  6:     Assert.IsTrue(_myComponent.EverythingIsFine);
  7: }

“It’s simple. Either the method throws an exception, or at the very least – the EverythingIsFine property won’t be set to “True”, so the assert will catch the problem. But in their case, no exception was thrown and Everything wasn’t Fine,  but the Assert call wasn’t raising a red flag – unless they stepped through, in which case it did. What’s going on?

The basic problem is that to many developers, NUnit is a kind of magic. You write a self-contained little bit of code, the [Test] method, but you don’t call it yourself, you don’t get a feel for the whole execution flow. The result – developers don’t exercise the same sort of judgement they do on their own application code.

The root of the problem here is that the [ExpectedException] attribute told NUnit to pass the test if an exception is thrown. NUnit’s Assertion utilities, however, use exceptions as the mechanism for failing tests – when an assertion is hit, it raises an exception – it can be an AssertionException. For various mock frameworks, it can be an ExpectationException. It doesn’t matter – it’s these exceptions that make the test fail, and not some behind-the-scenes magic. Because the test had an open-ended [ExpectedException] attribute, these exceptions were caught, fulfilling the condition, and NUnit was happy.

What can we do to avoid this?

  • Be explicit. Don’t try to catch ALL exceptions with [ExpectedException]. If you’re expecting an exception, you’re probably expecting a specific exception. Specify it.
  • Be aware of how your tools work. If NUnit works by throwing an exception, don’t wrap it with a try/catch. Your tests are C# code too, as is the plumbing to enable it. It plays by the same rules.

Testing cross-post.

Please ignore.