One of our customers wants to be able to show Google maps in our application. I understand that they have purchased a licence to allow them to use the Goggle API. Has anyone tried to usethis with the RadMap control? Is it legal? Are Telerik planning any support for this?
Thanks
Pete
3 Answers, 1 is accepted
Thank you for contacting us.
RadMap does not have a Google Maps provider and currently such cannot be implemented because of the additional protection which Google implemented in their service. Using the Google Maps tile server in a WPF application is not allowed. Currently, we do not plan to implement support for Google map API.
In your case, you mentioned that the customer has a license for using Google API. In this case, you can try creating a custom Google provider. You can take a look at the Implement custom map provider help article in our documentation.Technically a custom Google Maps provider for RadMap can be designed like the sample code below.
using System;using System.Collections.Generic;using System.Windows;using Telerik.Windows.Controls.Map; namespace GoogleMaps{ public class GoogleCustomProvider : TiledProvider, ICloneable { /// <summary> /// Identifies the <see cref="Mode"/> Mode dependency property. /// </summary> public static readonly DependencyProperty ModeProperty = DependencyProperty.Register( "Mode", typeof(GoogleCustomMapMode), typeof(GoogleCustomProvider), new PropertyMetadata(ModeChanged)); private ISpatialReference projection = new MercatorProjection(); private Dictionary<GoogleCustomMapMode, string> mapModeSource = new Dictionary<GoogleCustomMapMode, string>(); /// <summary> /// Initializes a new instance of the GoogleCustomProvider class. /// </summary> public GoogleCustomProvider() : base() { TiledMapSource source = new GoogleStreetCustomSource(); this.MapSources.Add(source.UniqueId, source); this.mapModeSource[GoogleCustomMapMode.Street] = source.UniqueId; source = new GoogleSatelliteCustomSource(); this.MapSources.Add(source.UniqueId, source); this.mapModeSource[GoogleCustomMapMode.Satellite] = source.UniqueId; source = new GoogleSatelliteHybridCustomSource(); this.MapSources.Add(source.UniqueId, source); this.mapModeSource[GoogleCustomMapMode.SatelliteHybrid] = source.UniqueId; source = new GooglePhysicalCustomSource(); this.MapSources.Add(source.UniqueId, source); this.mapModeSource[GoogleCustomMapMode.Physical] = source.UniqueId; source = new GooglePhysicalHybridCustomSource(); this.MapSources.Add(source.UniqueId, source); this.mapModeSource[GoogleCustomMapMode.PhysicalHybrid] = source.UniqueId; this.SetupCommands(); } /// <summary> /// Gets or sets map mode. /// </summary> public GoogleCustomMapMode Mode { get { return (GoogleCustomMapMode)this.GetValue(ModeProperty); } set { this.SetValue(ModeProperty, value); } } /// <summary> /// Returns the SpatialReference for the map provider. /// </summary> public override ISpatialReference SpatialReference { get { return this.projection; } } public new object Clone() { GoogleCustomProvider clone = new GoogleCustomProvider(); this.InheritCurrentSource(clone); this.InheritParameters(clone); return clone; } private static void ModeChanged(DependencyObject source, DependencyPropertyChangedEventArgs eventArgs) { GoogleCustomProvider provider = source as GoogleCustomProvider; if (provider != null) { provider.OnMapModeChanged((GoogleCustomMapMode)eventArgs.OldValue, (GoogleCustomMapMode)eventArgs.NewValue); } } /// <summary> /// MapModeChanged handler. /// </summary> /// <param name="newMode">New map mode.</param> /// <param name="oldMode">Old map mode.</param> private void OnMapModeChanged(GoogleCustomMapMode oldMode, GoogleCustomMapMode newMode) { this.SetMapSource(this.mapModeSource[newMode]); } private void SetupCommands() { this.CommandBindingCollection.Clear(); this.RegisterSetSourceCommand( typeof(GoogleStreetCustomSource), "Street", null, new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/road.png", UriKind.Relative), null, null); this.RegisterSetSourceCommand( typeof(GoogleSatelliteCustomSource), "Satellite", null, new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative), null, null); this.RegisterSetSourceCommand( typeof(GoogleSatelliteHybridCustomSource), "Satellite Hybrid", null, new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative), null, null); this.RegisterSetSourceCommand( typeof(GooglePhysicalCustomSource), "Physical", null, new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative), null, null); this.RegisterSetSourceCommand( typeof(GooglePhysicalHybridCustomSource), "Physical Hybrid", null, new Uri("/Telerik.Windows.Controls.DataVisualization;component/themes/aerial.png", UriKind.Relative), null, null); } } public class GoogleStreetCustomSource : GoogleCustomSourceBase { /// <summary> /// Initializes a new instance of the GoogleWorldImagerySource class. /// </summary> public GoogleStreetCustomSource() : base("m") { } } public class GoogleSatelliteCustomSource : GoogleCustomSourceBase { /// <summary> /// Initializes a new instance of the GoogleWorldImagerySource class. /// </summary> public GoogleSatelliteCustomSource() : base("s") { } } public class GoogleSatelliteHybridCustomSource : GoogleCustomSourceBase { /// <summary> /// Initializes a new instance of the GoogleWorldImagerySource class. /// </summary> public GoogleSatelliteHybridCustomSource() : base("y") { } } public class GooglePhysicalCustomSource : GoogleCustomSourceBase { /// <summary> /// Initializes a new instance of the GoogleWorldImagerySource class. /// </summary> public GooglePhysicalCustomSource() : base("t") { } } public class GooglePhysicalHybridCustomSource : GoogleCustomSourceBase { /// <summary> /// Initializes a new instance of the GoogleWorldImagerySource class. /// </summary> public GooglePhysicalHybridCustomSource() : base("p") { } } public class GoogleCustomSourceBase : TiledMapSource { private const string UrlFormat = @"http://mt{0}.google.com/vt/lyrs={1}&z={2}&x={3}&y={4}"; private int server = 0; private string mapLayers; /// <summary> /// Initializes a new instance of the GoogleWorldMapSourceBase class. /// </summary> public GoogleCustomSourceBase(string mapLayers) : base(0, 19, 256, 256) { this.mapLayers = mapLayers; } /// <summary> /// Initialize provider. /// </summary> public override void Initialize() { // Raise provider initialized event. this.RaiseInitializeCompleted(); } /// <summary> /// Gets the image URI. /// </summary> /// <param name="tileLevel">Tile level.</param> /// <param name="tilePositionX">Tile X.</param> /// <param name="tilePositionY">Tile Y.</param> /// <returns>URI of image.</returns> protected override Uri GetTile(int tileLevel, int tilePositionX, int tilePositionY) { int zoomLevel = ConvertTileToZoomLevel(tileLevel); string url = string.Empty; string prefix = string.Empty; this.server = (this.server + 1) % 4; url = string.Format(UrlFormat, server, this.mapLayers, zoomLevel, tilePositionX, tilePositionY); url = ProtocolHelper.SetScheme(url); return new Uri(url); } } /// <summary> /// Represents map modes. /// </summary> public enum GoogleCustomMapMode { Street, Satellite, SatelliteHybrid, Physical, PhysicalHybrid }}<telerik:RadMap x:Name="radMap"> <telerik:RadMap.Provider> <local:GoogleCustomProvider Mode="SatelliteHybrid" /> </telerik:RadMap.Provider></telerik:RadMap>Regards,
Dinko
Progress Telerik
Hi Dinko,
I have attempted to copy your code in a project there are no errors and the project builds but I get an error:
System.Windows.Markup.XamlParseException occurred
HResult=-2146233087
LineNumber=11
LinePosition=10
Message='The invocation of the constructor on type 'Telerik.Windows.Controls.RadMap' that matches the specified binding constraints threw an exception.' Line number '11' and line position '10'.
Source=PresentationFramework
StackTrace:
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at GoogleMaps.Page1.InitializeComponent()
InnerException:
HResult=-2146233036
Message=The type initializer for 'Telerik.Windows.Controls.TelerikLicense' threw an exception.
Source=Telerik.Windows.Controls
TypeName=Telerik.Windows.Controls.TelerikLicense
StackTrace:
at Telerik.Windows.Controls.TelerikLicense.Verify(FrameworkElement targetControl)
at Telerik.Windows.Controls.RadMap..ctor()
InnerException:
HResult=-2146233078
Message=Request failed.
Source=Telerik.Windows.Controls
StackTrace:
at Telerik.Windows.Controls.TelerikLicense.IsSdkSamplesBrowser()
at Telerik.Windows.Controls.TelerikLicense..cctor()
InnerException:
Hi Joe,
Were you able to make this work?
I used Dinko's code to create a sample project but I couldn't reproduce the error. Can you please take a look at it and let me know if I am missing something?
Regards,
Martin Ivanov
Progress Telerik
This should still work, but there are some Google API license concerns that you should keep in mind. You can find more information here: https://stackoverflow.com/questions/58846393/how-to-apply-api-key-to-google-maps-tile-server-url

