Workaround: Public Class MyLocalMapProvider Inherits LocalMapProvider Public Overrides Sub ViewportChanged(viewport As IMapViewport, action As ViewportChangeAction) If Not Me.Initialized Then Me.Initialize() Return End If Dim tilesToDraw As List(Of MapVisualElement) = DirectCast(Me.GetType().BaseType.GetField("tilesToDraw", BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(Me), List(Of MapVisualElement)) Dim numOfTilesX As Integer = CInt(Math.Ceiling(CDbl((viewport.ViewportInPixels.Width)) / Me.TileSize.Width)) + 2 Dim numOfTilesY As Integer = CInt(Math.Ceiling(CDbl((viewport.ViewportInPixels.Height)) / Me.TileSize.Height)) + 2 Dim maxNumberOfTilesY As Integer = If((viewport.ZoomLevel = 1), 2, (viewport.ZoomLevel - 1) << 2) numOfTilesY = Math.Min(numOfTilesY, maxNumberOfTilesY) Dim topLeftTile As Point = MapTileSystemHelper.PixelXYToTileXY(-viewport.PanOffset.Width, -viewport.PanOffset.Height) Dim numberOfTiles As Integer = 2 << (viewport.ZoomLevel - 1) Dim startX As Integer = CInt(viewport.PanOffset.Width) Mod Me.TileSize.Width Dim startY As Integer = CInt(viewport.PanOffset.Height) Mod Me.TileSize.Height If startX > 0 Then startX -= Me.TileSize.Width End If For i As Integer = 0 To numOfTilesY - 1 For j As Integer = 0 To numOfTilesX - 1 Dim x As Integer = startX + j * Me.TileSize.Width Dim y As Integer = startY + i * Me.TileSize.Height Dim tileX As Integer = (topLeftTile.X + j) Mod numberOfTiles Dim tileY As Integer = (topLeftTile.Y + i) Mod numberOfTiles If tileX < 0 Then tileX += numberOfTiles End If tilesToDraw.Add(New MapTile(Me.GetTileImage(tileX, tileY, viewport.ZoomLevel), New Rectangle(New Point(x, y), Me.TileSize))) Next Next End Sub End Class
How to reproduce: Change the current culture so that a comma is used as a decimal separator, the Elevations example will fail with a (400) Bar Request error. Workaround: create a custom BingRestMapProvider class public class CustomBingRestMapProvider : BingRestMapProvider { protected override string GetPointsString(List<PointG> points) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < points.Count; i++) { PointG point = points[i]; if (i > 0) { sb.Append(","); } sb.Append(point.Latitude.ToString(CultureInfo.InvariantCulture) + "," + point.Longitude.ToString(CultureInfo.InvariantCulture)); } return sb.ToString(); } }
To reproduce: - Use a DataTable as a data source for SqlGeospatialDataReader. - An exception will occur. Workaround: Convert the data table to a simple list of custom objects.
Until released use the following custom implementation: public partial class RoadOnDemandForm : RadForm { public RoadOnDemandForm() { InitializeComponent(); string cacheFolder = @"..\..\cache"; BingRestMapProvider bingProvider = new MyBingRestMapProvider(); bingProvider.Culture = System.Threading.Thread.CurrentThread.CurrentCulture; bingProvider.ImagerySet = ImagerySet.Road; bingProvider.UseSession = true; bingProvider.BingKey = "YourApiKey"; LocalFileCacheProvider cache = new LocalFileCacheProvider(cacheFolder); bingProvider.CacheProvider = cache; this.radMap1.MapElement.Providers.Add(bingProvider); } } public class MyBingRestMapProvider : BingRestMapProvider { private const string ImageryMetadataServiceUri = "https://dev.virtualearth.net/REST/v1/Imagery/Metadata/{set}?output=json&key={key}&c={culture}&dir={directory}"; protected override void InitializeImageryService() { typeof(BingRestMapProvider).GetField("tileMetadataInfo", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).SetValue(this, null); try { string uriString = ImageryMetadataServiceUri; uriString = uriString.Replace("{set}", "RoadOnDemand"); uriString = uriString.Replace("{key}", string.IsNullOrEmpty(this.SessionId) ? this.BingKey : this.SessionId); uriString = uriString.Replace("{culture}", this.Culture.ToString()); uriString = uriString.Replace("{directory}", "0"); WebClient client = new WebClient(); client.DownloadStringCompleted += this.InitializeImageryMetadataCompleted; client.DownloadStringAsync(new Uri(uriString, UriKind.Absolute)); } catch (Exception ex) { throw new Exception(string.Format("Imagery Service Exception: {0}", ex.Message)); } } }
How to reproduce: public partial class Form3 : Form { public Form3() { InitializeComponent(); MapLayer pointLayer = new MapLayer("PointG"); pointLayer.ClusterStrategy = new ElementClusterStrategy(); pointLayer.ClusterDistance = 100; this.radMap1.Layers.Add(pointLayer); MapPin pin1 = new MapPin(new PointG(45d, 15d)) { BackColor = Color.Coral, ToolTipText = "Tool Tip1" }; MapPin pin2 = new MapPin(new PointG(44d, 18d)) { BackColor = Color.Coral, ToolTipText = "Tool Tip2" }; this.radMap1.Layers["PointG"].Add(pin1); this.radMap1.Layers["PointG"].Add(pin2); this.SetupProviders(); } private void radMap1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e) { MapCluster cluster = sender as MapCluster; if (cluster != null && cluster.ClusteredItems.Count == 1) { cluster.ToolTipText = ((MapPin)cluster.ClusteredItems[0]).ToolTipText; } } private void SetupProviders() { string cacheFolder = @"..\..\cache"; BingRestMapProvider bingProvider = new BingRestMapProvider(); bingProvider.Culture = System.Threading.Thread.CurrentThread.CurrentCulture; bingProvider.ImagerySet = ImagerySet.Road; bingProvider.UseSession = true; bingProvider.BingKey = "..."; LocalFileCacheProvider cache = new LocalFileCacheProvider(cacheFolder); bingProvider.CacheProvider = cache; this.radMap1.MapElement.Providers.Add(bingProvider); bingProvider.InitializationComplete += bingProvider_InitializationComplete; } private void bingProvider_InitializationComplete(object sender, EventArgs e) { this.radMap1.BringIntoView(new PointG(45d, 15d), 5); } } Workaround: handle the ToolTipNeededEvent private void radMap1_ToolTipTextNeeded(object sender, Telerik.WinControls.ToolTipTextNeededEventArgs e) { MapCluster cluster = sender as MapCluster; if (cluster != null && cluster.ClusteredItems.Count == 1) { cluster.ToolTipText = ((MapPin)cluster.ClusteredItems[0]).ToolTipText; } }
Error: System.ArgumentException was unhandled HResult=-2147024809 Message=An item with the same key has already been added. Source=mscorlib StackTrace: at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add) at Telerik.WinControls.UI.DbfHeader.CreateExtendedPropertySet() at Telerik.WinControls.UI.DbfReader..ctor(Stream stream, ExtendedPropertySet propertySet, Encoding encoding) at Telerik.WinControls.UI.ShapeFileReader.Read(ShapeFileReaderParameters parameters) at _1125357MapShapeFiles.RadForm1..ctor() in d:\Projects\1125357MapShapeFiles\RadForm1.cs:line 37 at _1125357MapShapeFiles.Program.Main() in d:\Projects\1125357MapShapeFiles\Program.cs:line 17 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException:
You can find attached a sample project, video, demonstrating the steps and a screenshot of the error. Workaround: public class MyMapVisualElementFactory : MapVisualElementFactory { public override MapVisualElement CreatePolyline(Collection<PointG> points) { return new MyMapPolyline(points); } } public class MyMapPolyline : MapPolyline { private FieldInfo pathsField; private FieldInfo boundingRectsField; private FieldInfo isInViewportField; public MyMapPolyline(Collection<PointG> points) : base(points) { this.pathsField = typeof(MapPolyline).GetField("paths", BindingFlags.Instance | BindingFlags.NonPublic); this.boundingRectsField = typeof(MapPolyline).GetField("boundingRects", BindingFlags.Instance | BindingFlags.NonPublic); this.isInViewportField = typeof(MapPolyline).GetField("isInViewport", BindingFlags.Instance | BindingFlags.NonPublic); } public override void ViewportChanged(IMapViewport viewport, ViewportChangeAction action) { if ((action & ViewportChangeAction.All) == action) { long mapSize = MapTileSystemHelper.MapSize(viewport.ZoomLevel); List<GraphicsPath> paths = new List<GraphicsPath>(); List<RectangleL> boundingRects = new List<RectangleL>(); long start = viewport.PanOffset.Width; int maxWraparounds = 1; while (start + mapSize < viewport.ViewportInPixels.Width) { maxWraparounds++; start += mapSize; } for (int i = -1; i <= maxWraparounds; i++) { GraphicsPath path = new GraphicsPath(); List<PointF> drawPoints = new List<PointF>(); foreach (PointG p in this.Points) { PointL pixel = MapTileSystemHelper.LatLongToPixelXY(p.Latitude, p.Longitude, viewport.ZoomLevel); drawPoints.Add(new PointF(pixel.X + i * mapSize, pixel.Y)); } path.AddLines(drawPoints.ToArray()); RectangleF rect = path.GetBounds(); RectangleF view = new RectangleF(viewport.ViewportInPixels.X, viewport.ViewportInPixels.Y, viewport.ViewportInPixels.Width, viewport.ViewportInPixels.Height); if (rect.IntersectsWith(view)) { paths.Add(path); } boundingRects.Add(new RectangleL((long)rect.X, (long)rect.Y, (long)rect.Width, (long)rect.Height)); } this.pathsField.SetValue(this, paths); this.boundingRectsField.SetValue(this, boundingRects); } if (action != ViewportChangeAction.None) { this.isInViewportField.SetValue(this, false); List<RectangleL> boundingRects = this.boundingRectsField.GetValue(this) as List<RectangleL>; foreach (RectangleL rect in boundingRects) { if (viewport.ViewportInPixels.IntersectsWith(rect)) { this.isInViewportField.SetValue(this, true); } } } } } public class MyMapVisualElementFactory : MapVisualElementFactory { public override MapVisualElement CreatePolyline(Collection<PointG> points) { return new MyMapPolyline(points); } } public class MyMapPolyline : MapPolyline { private FieldInfo pathsField; private FieldInfo boundingRectsField; private FieldInfo isInViewportField; public MyMapPolyline(Collection<PointG> points) : base(points) { this.pathsField = typeof(MapPolyline).GetField("paths", BindingFlags.Instance | BindingFlags.NonPublic); this.boundingRectsField = typeof(MapPolyline).GetField("boundingRects", BindingFlags.Instance | BindingFlags.NonPublic); this.isInViewportField = typeof(MapPolyline).GetField("isInViewport", BindingFlags.Instance | BindingFlags.NonPublic); } public override void ViewportChanged(IMapViewport viewport, ViewportChangeAction action) { if ((action & ViewportChangeAction.All) == action) { long mapSize = MapTileSystemHelper.MapSize(viewport.ZoomLevel); List<GraphicsPath> paths = new List<GraphicsPath>(); List<RectangleL> boundingRects = new List<RectangleL>(); long start = viewport.PanOffset.Width; int maxWraparounds = 1; while (start + mapSize < viewport.ViewportInPixels.Width) { maxWraparounds++; start += mapSize; } for (int i = -1; i <= maxWraparounds; i++) { GraphicsPath path = new GraphicsPath(); List<PointF> drawPoints = new List<PointF>(); foreach (PointG p in this.Points) { PointL pixel = MapTileSystemHelper.LatLongToPixelXY(p.Latitude, p.Longitude, viewport.ZoomLevel); drawPoints.Add(new PointF(pixel.X + i * mapSize, pixel.Y)); } path.AddLines(drawPoints.ToArray()); RectangleF rect = path.GetBounds(); RectangleF view = new RectangleF(viewport.ViewportInPixels.X, viewport.ViewportInPixels.Y, viewport.ViewportInPixels.Width, viewport.ViewportInPixels.Height); if (rect.IntersectsWith(view)) { paths.Add(path); } boundingRects.Add(new RectangleL((long)rect.X, (long)rect.Y, (long)rect.Width, (long)rect.Height)); } this.pathsField.SetValue(this, paths); this.boundingRectsField.SetValue(this, boundingRects); } if (action != ViewportChangeAction.None) { this.isInViewportField.SetValue(this, false); List<RectangleL> boundingRects = this.boundingRectsField.GetValue(this) as List<RectangleL>; foreach (RectangleL rect in boundingRects) { if (viewport.ViewportInPixels.IntersectsWith(rect)) { this.isInViewportField.SetValue(this, true); } } } } }
To reproduce: - Create a shape with QGIS and add it to RadMap using the approach described in the documentation: http://docs.telerik.com/devtools/winforms/map/file-readers/esri-shapefile-reader
https://msdn.microsoft.com/en-us/library/ff701717.aspx
How to reproduce: change the Windows culture to Greek and start the OSM example
How to reproduce: check the attached video Workaround: create a custom MapSearchBarElement public class MyRadMap : RadMap { public override string ThemeClassName { get { return typeof(RadMap).FullName; } } protected override RadMapElement CreateMapElement() { return new MyRadMapElement(); } } public class MyRadMapElement : RadMapElement { protected override Type ThemeEffectiveType { get { return typeof(RadMapElement); } } protected override MapSearchBarElement CreateSearchBarElement() { return new MyMapSearchBarElement(this); } } public class MyMapSearchBarElement : MapSearchBarElement { public MyMapSearchBarElement(MyRadMapElement mapElement) : base(mapElement) { } protected override Type ThemeEffectiveType { get { return typeof(MapSearchBarElement); } } protected override void SearchProviderSearchError(object sender, SearchErrorEventArgs e) { IMapSearchProvider provider = sender as IMapSearchProvider; provider.SearchCompleted -= SearchProviderSearchCompleted; provider.SearchError -= SearchProviderSearchError; if (this.ElementTree != null) { UnsubscribeToTextBoxEvents(this.SearchTextBoxElement); RadMessageBox.SetThemeName(this.ElementTree.ThemeName); RadMessageBox.Show(e.Error.Message); SubscribeToTextBoxEvents(this.SearchTextBoxElement); } } protected override void SubscribeToTextBoxEvents(RadTextBoxElement textBox) { textBox.TextChanged += OnSearchTextBoxTextChanged; textBox.KeyDown += OnSearchTextBoxKeyDown; } protected override void UnsubscribeToTextBoxEvents(RadTextBoxElement textBox) { textBox.TextChanged -= OnSearchTextBoxTextChanged; textBox.KeyDown -= OnSearchTextBoxKeyDown; } private void OnSearchTextBoxKeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { if (e.KeyCode == Keys.Enter) { this.Search(this.SearchTextBoxElement.Text); } } }
In the scenario below one should be able to access the defined UserData value in the SearchCompleted event handler How to reproduce: protected override void OnLoad(EventArgs e) { base.OnLoad(e); this.radMap1.ShowSearchBar = true; BingRestMapProvider bingProvider = this.radMap1.Providers[0] as BingRestMapProvider; this.radMap1.MapElement.SearchBarElement.SearchProvider = bingProvider; this.radMap1.MapElement.SearchBarElement.SearchProvider.SearchCompleted += BingProvider_SearchCompleted; } private void BingProvider_SearchCompleted(object sender, SearchCompletedEventArgs e) { Telerik.WinControls.UI.Map.RectangleG allPoints = new Telerik.WinControls.UI.Map.RectangleG(double.MinValue, double.MaxValue, double.MaxValue, double.MinValue); this.radMap1.Layers["Pins"].Clear(); foreach (Telerik.WinControls.UI.Map.Bing.Location location in e.Locations) { Telerik.WinControls.UI.Map.PointG point = new Telerik.WinControls.UI.Map.PointG(location.Point.Coordinates[0], location.Point.Coordinates[1]); MapPin pin = new MapPin(point); pin.Size = new System.Drawing.Size(20, 40); pin.BackColor = Color.Red; pin.ToolTipText = location.Address.FormattedAddress; this.radMap1.MapElement.Layers["Pins"].Add(pin); allPoints.North = Math.Max(allPoints.North, point.Latitude); allPoints.South = Math.Min(allPoints.South, point.Latitude); allPoints.West = Math.Min(allPoints.West, point.Longitude); allPoints.East = Math.Max(allPoints.East, point.Longitude); } if (e.Locations.Length > 0) { if (e.Locations.Length == 1) { this.radMap1.BringIntoView(new Telerik.WinControls.UI.Map.PointG(e.Locations[0].Point.Coordinates[0], e.Locations[0].Point.Coordinates[1])); } else { this.radMap1.MapElement.BringIntoView(allPoints); this.radMap1.Zoom(this.radMap1.MapElement.ZoomLevel - 1); } } else { RadMessageBox.Show("No result found for the provided search query!"); } } Telerik.WinControls.UI.Map.Bing.SearchRequest request; private void radButton1_Click(object sender, EventArgs e) { Telerik.WinControls.UI.MapLayer pinsLayer = new MapLayer("Pins"); this.radMap1.Layers.Add(pinsLayer); request = new SearchRequest(); request.Query = "San Marino"; request.SearchOptions.Count = 10; request.SearchOptions.QueryParse = true; request.UserData = "Tooltip"; BingRestMapProvider bingProvider = this.radMap1.Providers[0] as BingRestMapProvider; bingProvider.SearchAsync(request); } Workaround: if possible cache the data to be accessed at a later stage
A sample for the required functionality: public void AddMarker(RadMap Map) { SearchRequest r = new SearchRequest(); r.Query = "Paris, France"; r.UserData = new Guid(); bingProvider.SearchCompleted += BingProvider_SearchCompleted; bingProvider.SearchAsync(r); } private void BingProvider_SearchCompleted(object sender, SearchCompletedEventArgs e) { //one cannot access the UserData here }
1. Open the demo application >> Map >> Search example. 2. Enter some text and press Enter. 3. Move the mouse a little bit and you will notice the search box looses focus. Workaround: this.radMap1.MapElement.SearchBarElement.SearchTextBoxElement.TextBoxItem.LostFocus+=TextBoxItem_LostFocus; private void TextBoxItem_LostFocus(object sender, EventArgs e) { this.radMap1.MapElement.SearchBarElement.SearchTextBoxElement.TextBoxItem.TextBoxControl.Focus(); }