[GIS] Creating MapTips programmatically for programmatically-created KML layer using ArcGIS API for Silverlight

arcgis-silverlight-apikml

The few examples and forum posts that I have found all use KML layers defined in XAML at design-time with nested MapTip templates binding to one or more Placemark attributes e.g. name or ExtendedData values (using the ExtendedDataConverter class provided in the example here).

I am looking for a way to programmatically configure map tips on a programmatically-created KML layer at runtime. I can display empty map tips if I assign a MapTip instance to every Graphic in the KmlLayer, but cannot figure out how to dynamically bind the MapTip to the Attribute data in the Graphic. I have inspected the graphic elements and confirmed that they do indeed contain the correct attribute data from the KML document.

Does anyone have an idea as to how this can be accomplished?

Best Answer

KmlLayer is alien to me, but I see it has a MapTip property same as FeatureLayer. Here's what we've got for FeatureLayers. These two lines are present in my main MapPage.xaml.cs in an event handler for the layer Initialized event.

FeatureLayerInfo lyrInfo = fLayer.LayerInfo;
fLayer.MapTip = CreateTipWindow(lyrInfo, fLayer.OutFields);

private PopupWindow CreateTipWindow(FeatureLayerInfo lyrInfo, List<string> outFields)
{
  //edited to omit details not relevent...
  Dictionary<string, string> aliases = new Dictionary<string, string>();
  foreach (Field f in lyrInfo.Fields) 
  { 
    if (f.Name != lyrInfo.DisplayField) aliases.Add(f.Name, f.Alias); 
  }
  PopupWindow tipWindow = new PopupWindow() { ShowArrow = false, ShowCloseButton = false };
  tipWindow.Content = CreateFeatureTipContent(outFields, aliases);
  return tipWindow;
}

private FrameworkElement CreateFeatureTipContent(List<string> fields, Dictionary<string, string> aliases)
{
    StackPanel stackBox = new StackPanel() { Margin = new Thickness(4, 1, 4, 1), Orientation = Orientation.Vertical };

    foreach (string field in fields)
    {
        if (aliases.Keys.Contains(field))
        {
            TextBlock valueBlock = new TextBlock() { TextWrapping = TextWrapping.NoWrap };
            Binding valueBinding = new Binding() { Path = new PropertyPath(string.Format("[{0}]", field)), StringFormat = aliases[field] + ": {0}" };
            valueBinding.Converter = new DateTimeConverter(); //MC 2013-01 added this to tweak any Local DateTimes.
            valueBlock.SetBinding(TextBlock.TextProperty, valueBinding);
            stackBox.Children.Add(valueBlock);
        }
    }

    return stackBox;
}

We are using the PopupWindow class from the ESRI.SilverlightViewer.Controls library distrubuted with this viewer (from which we've learned a great deal, BTW), but PopupWindow simply derives from ContentControl, so rolling one's own is minor, if you want.