Search code examples
c#win-universal-appbinguwp-maps

Customize MapIcon in MapControl UWP


Im developing application for UWP. My purpose was to optymalize map points rendering on bing map.I started from clustering custom markers with operation map.children.add(). After cluster group of pins, i'm adding pin with generated dependencyobject in xaml. Every change position on map is refreshing all pins which are currently showed. Its working very slow. So i tried to use MapElement.Add(). Its working fine but i cant add generic image ( xaml ) Code (_native map is MapControl) :

 var mapIcon = new MapIcon();
    mapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Images/icon.png"));
    mapIcon.Location = new Geopoint(snPosition);
    mapIcon.Title = "Some label".ToString();
    _nativemap.MapElements.Add(mapIcon);

Is there any way to customize label of mapIcon (position, color etc) or generate stream from xaml file to show it as actual mapIcon image ??


Solution

  • To add mapicon with image as stream ( generated by xaml ) on map

    I don't know how you generate a image stream by xaml, I guess that you have a control or something and you use RenderTargetBitmap to generate a image source which is populated with the combined contents of a XAML visual tree. Then you can use BitmapEncoder to create a InMemoryRandomAccessStream.

    To demonstrate how to use BitmapEncoder, I take the scenario 1 of official MapControl sample for example here:

    Create a SymbolIcon for the MapIcon and create a Button to put MapIcon on the map:

    <Grid x:Name="imgContainer" Margin="0,5" Width="20" Height="25">
        <SymbolIcon Symbol="AddFriend" Foreground="Red" />
    </Grid>
    <Button Content="Place MapIcon" Click="Button_Click" />
    

    Code behind:

    private async void Button_Click(object sender, RoutedEventArgs e)
    {
        //render symbolicon to bmp
        RenderTargetBitmap renderbmp = new RenderTargetBitmap();
        await renderbmp.RenderAsync(imgContainer);
    
        using (InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream())
        {
            //create a bitmap encoder
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            //write pixels into this encoder
            var pixels = await renderbmp.GetPixelsAsync();
            var reader = DataReader.FromBuffer(pixels);
            byte[] bytes = new byte[reader.UnconsumedBufferLength];
            reader.ReadBytes(bytes);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight,
                (uint)renderbmp.PixelWidth, (uint)renderbmp.PixelHeight, 0, 0, bytes);
            await encoder.FlushAsync();
            mapIconStreamReference = RandomAccessStreamReference.CreateFromStream(stream);
    
            //create mapIcon
            var mapIcon = new MapIcon();
            mapIcon.Image = mapIconStreamReference;
            mapIcon.Location = new Geopoint(myMap.Center.Position);
            mapIcon.Title = "Some label".ToString();
            myMap.MapElements.Add(mapIcon);
        }
    }
    

    Rendering image of this demo: enter image description here