private static void UpdateGraphicsAndRenderer(KmlGraphicsLayer layer, UniqueValueRenderer renderer, string key) { foreach (var graphic in layer.Graphics) { var f = (PlacemarkDescriptor)graphic.GetValue(FeaturePlacemarkerDescriptorProperty); if (f.Symbol.style.IconHref != null && f.Symbol.style.IconHref.ToLower() == key) { graphic.Symbol = PointSymbolDescriptor.GetDefaultSymbol(); ComputeIconTranslationValues(f.Symbol.style, graphic.Symbol as KmlPlaceMarkerSymbol, ((graphic.Symbol as KmlPlaceMarkerSymbol).Fill as ImageBrush).ImageSource as BitmapImage); string l = null, d = null; GetRendererInfo(f, f.Symbol.style, out l, out d); var info = renderer.Infos.FirstOrDefault(i => i.Label == l); if (info != null) { info.Symbol = graphic.Symbol; } } } }
/// <summary> /// Extracts a point from the input element and applies style information to the placemark descriptor. /// </summary> /// <param name="kmlStyle">KML Style information.</param> /// <param name="point">Point geometry information.</param> /// <returns>A PlacemarkDescriptor object representing the feature.</returns> private static PlacemarkDescriptor ExtractPoint(KMLStyle kmlStyle, XElement point) { XNamespace kmlNS = point.Name.Namespace; XElement coord = point.Element(kmlNS + "coordinates"); if (coord != null) { // Extract geometry ESRI.ArcGIS.Client.Geometry.Geometry geom = ExtractCoordinate(coord.Value); if (geom != null) { // Create symbol and use style information PointSymbolDescriptor sym = new PointSymbolDescriptor(); sym.style = kmlStyle; // Create feature descriptor from geometry and other information PlacemarkDescriptor fd = new PlacemarkDescriptor() { Geometry = geom, Symbol = sym }; return fd; } } return null; }
/// <summary> /// Creates graphic elements and adds them to the graphics layer. /// </summary> /// <param name="layer">Graphics layer that will have features added to it.</param> /// <param name="images">Dictionary of images coming from kmz content or from previous parsing</param> public void CreateGraphics(KmlGraphicsLayer layer, IDictionary <string, ImageBrush> images) { if (layer == null) { return; } GraphicCollection graphics = new GraphicCollection(); UniqueValueRenderer renderer = new UniqueValueRenderer(); // dummy renderer used to create the legend items (since creation of the swatches from the symbol is not that obvious) // Process each metadata feature in the list foreach (PlacemarkDescriptor feature in placemarks) { KMLStyle style = feature.Symbol.style; if (style.ZipFile != null) { // Look for the image in the zip file if (style.IconImage == null && !String.IsNullOrEmpty(style.IconHref)) { style.IconImage = GetIconImage(style.ZipFile, style.IconHref.ToLower()); } style.ZipFile.Dispose(); style.ZipFile = null; } //Define handlers upfront so we can unhook from them #if SILVERLIGHT EventHandler <RoutedEventArgs> #else EventHandler #endif imageCompleted = null; #if SILVERLIGHT EventHandler <ExceptionRoutedEventArgs> #else EventHandler <ExceptionEventArgs> #endif imageFailed = null; // If the style has an HREF then it is associated with an image if (style.IconImage == null && !String.IsNullOrEmpty(style.IconHref)) { // If the image is already loaded in the image dictionary, use it if (images.ContainsKey(style.IconHref.ToLower())) { style.IconImage = images[style.IconHref.ToLower()]; } else { // Get the image using the HREF and store the image in the images dictionary so that if // other features reference it, it is cached style.IconImage = GetIconImage(style.IconHref); if (style.IconImage != null && (style.IconImage as ImageBrush).ImageSource != null) { var bi = (style.IconImage as ImageBrush).ImageSource as BitmapImage; if (bi != null) { imageFailed = (s, e) => { var b = s as BitmapImage; #if SILVERLIGHT if (imageCompleted != null) { b.ImageOpened -= imageCompleted; } if (imageFailed != null) { b.ImageFailed -= imageFailed; } #else if (imageCompleted != null) { b.DownloadCompleted -= imageCompleted; } if (imageFailed != null) { b.DownloadFailed -= imageFailed; } #endif var key = b.GetValue(BitmapImageKeyProperty) as string; layer.Dispatcher.BeginInvoke((Action) delegate { UpdateGraphicsAndRenderer(layer, renderer, key); }); }; #if SILVERLIGHT bi.ImageFailed += imageFailed; #else bi.DownloadFailed += imageFailed; #endif } } images.Add(style.IconHref.ToLower(), style.IconImage); } } // Create a new graphic from the metadata and construct the symbol using polymorphism Graphic g = new Graphic() { Geometry = feature.Geometry, Symbol = feature.Symbol.CreateSymbol(), TimeExtent = feature.TimeExtent }; g.SetValue(FeaturePlacemarkerDescriptorProperty, feature); // Create legend entry string label; string description; GetRendererInfo(feature, style, out label, out description); if (!string.IsNullOrEmpty(label) && !renderer.Infos.Any(info => info.Label == label)) { renderer.Infos.Add(new UniqueValueInfo { Label = label, Description = description, Symbol = g.Symbol }); } // Adjust and assign picture marker symbol properties if (g.Geometry is ESRI.ArcGIS.Client.Geometry.MapPoint && g.Symbol is KmlPlaceMarkerSymbol) { try { KmlPlaceMarkerSymbol ms = g.Symbol as KmlPlaceMarkerSymbol; // To match sizing of Google Earth, default size of point images is 40x40 ms.Height = 40; ms.Width = 40; ms.Fill = style.IconImage; ms.IconColor = style.IconColor; // Default to half the pixel size (width and height) if symbol offsets are 0 (supported in wpf and sl3) ImageBrush ib = ms.Fill; BitmapImage bi = ib.ImageSource as BitmapImage; #if SILVERLIGHT if (bi.PixelHeight == 0 || bi.PixelWidth == 0) #else if (bi.IsDownloading) #endif { imageCompleted = (s, e) => { var b = s as BitmapImage; #if SILVERLIGHT if (imageCompleted != null) { b.ImageOpened -= imageCompleted; } if (imageFailed != null) { b.ImageFailed -= imageFailed; } #else if (imageCompleted != null) { b.DownloadCompleted -= imageCompleted; } if (imageFailed != null) { b.DownloadFailed -= imageFailed; } #endif ComputeIconTranslationValues(style, ms, b); }; #if SILVERLIGHT bi.ImageOpened += imageCompleted; #else bi.DownloadCompleted += imageCompleted; #endif } else { ComputeIconTranslationValues(style, ms, bi); } } catch { g.Symbol = PointSymbolDescriptor.GetDefaultSymbol(); ComputeIconTranslationValues(style, g.Symbol as KmlPlaceMarkerSymbol, ((g.Symbol as KmlPlaceMarkerSymbol).Fill as ImageBrush).ImageSource as BitmapImage); var info = renderer.Infos.FirstOrDefault(i => i.Label == label); if (info != null) { info.Symbol = g.Symbol; } } } // Copy attributes values from metadata to graphic foreach (var attribute in feature.Attributes) { g.Attributes.Add(attribute.Key, attribute.Value); } // If the balloontext property has been assigned a value in the style associated with this // graphic feature, then add it to the attributes collection. if (!String.IsNullOrEmpty(style.BalloonText)) { g.Attributes.Add("balloonText", style.BalloonText); } // Add graphic to graphics layer graphics.Add(g); } layer.Graphics = graphics; // keep the renderer for further usage (when QueryLegendInfos is called) layer.RendererBasedOnStyle = renderer; }