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