diff --git a/LotsOfPolylinesRepro/WorkingWithMaps.sln b/LotsOfPolylinesRepro/WorkingWithMaps.sln new file mode 100644 index 0000000..6abd84e --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps.sln @@ -0,0 +1,27 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31611.283 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WorkingWithMaps", "WorkingWithMaps\WorkingWithMaps.csproj", "{09D2F154-E3FE-4377-B73C-2AA8028444A5}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.Build.0 = Release|Any CPU + {09D2F154-E3FE-4377-B73C-2AA8028444A5}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {61F7FB11-1E47-470C-91E2-47F8143E1572} + EndGlobalSection +EndGlobal diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml new file mode 100644 index 0000000..bf16747 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs new file mode 100644 index 0000000..5e6e813 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/App.xaml.cs @@ -0,0 +1,11 @@ +namespace WorkingWithMaps; + +public partial class App : Application +{ + public App() + { + InitializeComponent(); + + MainPage = new AppShell(); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml new file mode 100644 index 0000000..a7c946c --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml @@ -0,0 +1,14 @@ + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs new file mode 100644 index 0000000..b4e0944 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/AppShell.xaml.cs @@ -0,0 +1,9 @@ +namespace WorkingWithMaps; + +public partial class AppShell : Shell +{ + public AppShell() + { + InitializeComponent(); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs b/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs new file mode 100644 index 0000000..a3993cf --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/MauiProgram.cs @@ -0,0 +1,25 @@ +using Microsoft.Extensions.Logging; + +namespace WorkingWithMaps; + +public static class MauiProgram +{ + public static MauiApp CreateMauiApp() + { + var builder = MauiApp.CreateBuilder(); + builder + .UseMauiApp() + .ConfigureFonts(fonts => + { + fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); + fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); + }) + .UseMauiMaps(); + +#if DEBUG + builder.Logging.AddDebug(); +#endif + + return builder.Build(); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs new file mode 100644 index 0000000..bef88fa --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Models/Position.cs @@ -0,0 +1,38 @@ +using System.ComponentModel; + +namespace WorkingWithMaps.Models +{ + public class Position : INotifyPropertyChanged + { + Location _location; + + public string Address { get; } + public string Description { get; } + + public Location Location + { + get => _location; + set + { + if (Location == null || !_location.Equals(value)) + { + _location = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Location))); + } + } + } + + public Position(string address, string description, Location location) + { + Address = address; + Description = description; + Location = location; + } + + #region INotifyPropertyChanged + + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + } +} \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs new file mode 100644 index 0000000..b72896c --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Models/RandomPosition.cs @@ -0,0 +1,14 @@ +namespace WorkingWithMaps.Models +{ + static class RandomPosition + { + static Random Random = new Random(Environment.TickCount); + + public static Location Next(Location location, double latitudeRange, double longitudeRange) + { + return new Location( + location.Latitude + (Random.NextDouble() * 2 - 1) * latitudeRange, + location.Longitude + (Random.NextDouble() * 2 - 1) * longitudeRange); + } + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml new file mode 100644 index 0000000..ae5d948 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/AndroidManifest.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs new file mode 100644 index 0000000..06398d0 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainActivity.cs @@ -0,0 +1,10 @@ +using Android.App; +using Android.Content.PM; +using Android.OS; + +namespace WorkingWithMaps; + +[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] +public class MainActivity : MauiAppCompatActivity +{ +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs new file mode 100644 index 0000000..d1b99f9 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/MainApplication.cs @@ -0,0 +1,15 @@ +using Android.App; +using Android.Runtime; + +namespace WorkingWithMaps; + +[Application] +public class MainApplication : MauiApplication +{ + public MainApplication(IntPtr handle, JniHandleOwnership ownership) + : base(handle, ownership) + { + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml new file mode 100644 index 0000000..c04d749 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Android/Resources/values/colors.xml @@ -0,0 +1,6 @@ + + + #512BD4 + #2B0B98 + #2B0B98 + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs new file mode 100644 index 0000000..c054115 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/AppDelegate.cs @@ -0,0 +1,9 @@ +using Foundation; + +namespace WorkingWithMaps; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist new file mode 100644 index 0000000..e206a43 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Info.plist @@ -0,0 +1,34 @@ + + + + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSLocationAlwaysAndWhenInUseUsageDescription + Can we use your location at all times? + NSLocationWhenInUseUsageDescription + Can we use your location when your app is being used? + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs new file mode 100644 index 0000000..dd647e1 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/MacCatalyst/Program.cs @@ -0,0 +1,15 @@ +using ObjCRuntime; +using UIKit; + +namespace WorkingWithMaps; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs new file mode 100644 index 0000000..7da4ac5 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/Main.cs @@ -0,0 +1,16 @@ +using System; +using Microsoft.Maui; +using Microsoft.Maui.Hosting; + +namespace WorkingWithMaps; + +class Program : MauiApplication +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); + + static void Main(string[] args) + { + var app = new Program(); + app.Run(args); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml new file mode 100644 index 0000000..0c63b56 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Tizen/tizen-manifest.xml @@ -0,0 +1,15 @@ + + + + + + maui-appicon-placeholder + + + + + http://tizen.org/privilege/internet + + + + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml new file mode 100644 index 0000000..c3b5f8e --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml @@ -0,0 +1,8 @@ + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs new file mode 100644 index 0000000..807d7ba --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/App.xaml.cs @@ -0,0 +1,24 @@ +using Microsoft.UI.Xaml; + +// To learn more about WinUI, the WinUI project structure, +// and more about our project templates, see: http://aka.ms/winui-project-info. + +namespace WorkingWithMaps.WinUI; + +/// +/// Provides application-specific behavior to supplement the default Application class. +/// +public partial class App : MauiWinUIApplication +{ + /// + /// Initializes the singleton application object. This is the first line of authored code + /// executed, and as such is the logical equivalent of main() or WinMain(). + /// + public App() + { + this.InitializeComponent(); + } + + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest new file mode 100644 index 0000000..2bcb11e --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/Package.appxmanifest @@ -0,0 +1,43 @@ + + + + + + + $placeholder$ + User Name + $placeholder$.png + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest new file mode 100644 index 0000000..a9848fa --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/Windows/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs new file mode 100644 index 0000000..c054115 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/AppDelegate.cs @@ -0,0 +1,9 @@ +using Foundation; + +namespace WorkingWithMaps; + +[Register("AppDelegate")] +public class AppDelegate : MauiUIApplicationDelegate +{ + protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist new file mode 100644 index 0000000..d8412c2 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Info.plist @@ -0,0 +1,36 @@ + + + + + LSRequiresIPhoneOS + + UIDeviceFamily + + 1 + 2 + + UIRequiredDeviceCapabilities + + arm64 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + XSAppIconAssets + Assets.xcassets/appicon.appiconset + NSLocationAlwaysAndWhenInUseUsageDescription + Can we use your location at all times? + NSLocationWhenInUseUsageDescription + Can we use your location when your app is being used? + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs new file mode 100644 index 0000000..dd647e1 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Platforms/iOS/Program.cs @@ -0,0 +1,15 @@ +using ObjCRuntime; +using UIKit; + +namespace WorkingWithMaps; + +public class Program +{ + // This is the main entry point of the application. + static void Main(string[] args) + { + // if you want to use a different Application Delegate class from "AppDelegate" + // you can specify it here. + UIApplication.Main(args, null, typeof(AppDelegate)); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json b/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json new file mode 100644 index 0000000..edf8aad --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg new file mode 100644 index 0000000..9d63b65 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appicon.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/AppIcon/appiconfg.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf new file mode 100644 index 0000000..0a155fd Binary files /dev/null and b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Regular.ttf differ diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf new file mode 100644 index 0000000..94f874f Binary files /dev/null and b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Fonts/OpenSans-Semibold.ttf differ diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg new file mode 100644 index 0000000..abfaff2 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Images/dotnet_bot.svg @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt new file mode 100644 index 0000000..15d6244 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Raw/AboutAssets.txt @@ -0,0 +1,15 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories). Deployment of the asset to your application +is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. + + + +These files will be deployed with you package and will be accessible using Essentials: + + async Task LoadMauiAsset() + { + using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); + using var reader = new StreamReader(stream); + + var contents = reader.ReadToEnd(); + } diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg new file mode 100644 index 0000000..21dfb25 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Splash/splash.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml new file mode 100644 index 0000000..245758b --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Colors.xaml @@ -0,0 +1,44 @@ + + + + + #512BD4 + #DFD8F7 + #2B0B98 + White + Black + #E1E1E1 + #C8C8C8 + #ACACAC + #919191 + #6E6E6E + #404040 + #212121 + #141414 + + + + + + + + + + + + + + + #F7B548 + #FFD590 + #FFE5B9 + #28C2D1 + #7BDDEF + #C3F2F4 + #3E8EED + #72ACF1 + #A7CBF6 + + \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml new file mode 100644 index 0000000..1ec9d55 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Resources/Styles/Styles.xaml @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs new file mode 100644 index 0000000..0265e5a --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Templates/MapItemTemplateSelector.cs @@ -0,0 +1,15 @@ +using WorkingWithMaps.Models; + +namespace WorkingWithMaps.Templates; + +public class MapItemTemplateSelector : DataTemplateSelector +{ + public DataTemplate DefaultTemplate { get; set; } + public DataTemplate SanFranTemplate { get; set; } + + protected override DataTemplate OnSelectTemplate(object item, BindableObject container) + { + return ((Position)item).Address.Contains("San Francisco") ? SanFranTemplate : DefaultTemplate; + } +} + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs b/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs new file mode 100644 index 0000000..d16ff6a --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/ViewModels/PinItemsSourcePageViewModel.cs @@ -0,0 +1,82 @@ +using System.Collections; +using System.Collections.ObjectModel; +using System.Windows.Input; +using WorkingWithMaps.Models; + +namespace WorkingWithMaps.ViewModels; + +public class PinItemsSourcePageViewModel +{ + int _pinCreatedCount = 0; + readonly ObservableCollection _positions; + + public IEnumerable Positions => _positions; + + public ICommand AddLocationCommand { get; } + public ICommand RemoveLocationCommand { get; } + public ICommand ClearLocationsCommand { get; } + public ICommand UpdateLocationsCommand { get; } + public ICommand ReplaceLocationCommand { get; } + + public PinItemsSourcePageViewModel() + { + _positions = new ObservableCollection() + { + new Position("New York, USA", "The City That Never Sleeps", new Location(40.67, -73.94)), + new Position("Los Angeles, USA", "City of Angels", new Location(34.11, -118.41)), + new Position("San Francisco, USA", "Bay City", new Location(37.77, -122.45)) + }; + + AddLocationCommand = new Command(AddLocation); + RemoveLocationCommand = new Command(RemoveLocation); + ClearLocationsCommand = new Command(() => _positions.Clear()); + UpdateLocationsCommand = new Command(UpdateLocations); + ReplaceLocationCommand = new Command(ReplaceLocation); + } + + void AddLocation() + { + _positions.Add(NewPosition()); + } + + void RemoveLocation() + { + if (_positions.Any()) + { + _positions.Remove(_positions.First()); + } + } + + void UpdateLocations() + { + if (!_positions.Any()) + { + return; + } + + double lastLatitude = _positions.Last().Location.Latitude; + foreach (Position position in Positions) + { + position.Location = new Location(lastLatitude, position.Location.Longitude); + } + } + + void ReplaceLocation() + { + if (!_positions.Any()) + { + return; + } + + _positions[_positions.Count - 1] = NewPosition(); + } + + Position NewPosition() + { + _pinCreatedCount++; + return new Position( + $"Pin {_pinCreatedCount}", + $"Desc {_pinCreatedCount}", + RandomPosition.Next(new Location(39.8283459, -98.5794797), 8, 19)); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml new file mode 100644 index 0000000..38ddcb4 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml @@ -0,0 +1,45 @@ + + + + + + + + + 37.79752 + -122.40183 + + + 0.01 + 0.01 + + + + + + + + + 37.79752 + -122.40183 + + + + + + + 250 + + + + + + + diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs new file mode 100644 index 0000000..af17a94 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/CirclePage.xaml.cs @@ -0,0 +1,9 @@ +namespace WorkingWithMaps.Views; + +public partial class CirclePage : ContentPage +{ + public CirclePage() + { + InitializeComponent(); + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs new file mode 100644 index 0000000..7f16e19 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/CirclePageCode.cs @@ -0,0 +1,39 @@ +using Microsoft.Maui.Controls.Maps; +using Microsoft.Maui.Maps; +using Map = Microsoft.Maui.Controls.Maps.Map; + +namespace WorkingWithMaps.Views.Code +{ + public class CirclePageCode : ContentPage + { + public CirclePageCode() + { + Map map = new Map(); + + Location location = new Location(37.79752, -122.40183); + Pin pin = new Pin + { + Label = "Microsoft San Francisco", + Address = "1355 Market St, San Francisco CA", + Type = PinType.Place, + Location = location + }; + map.Pins.Add(pin); + + Circle circle = new Circle + { + Center = location, + Radius = new Distance(250), + StrokeColor = Color.FromArgb("#88FF0000"), + StrokeWidth = 8, + FillColor = Color.FromArgb("#88FFC0CB") + }; + map.MapElements.Add(circle); + + Title = "Circle demo"; + Content = map; + + map.MoveToRegion(new MapSpan(location, 0.01, 0.01)); + } + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs new file mode 100644 index 0000000..464fafe --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/GeocoderPageCode.cs @@ -0,0 +1,41 @@ +using Microsoft.Maui.Devices.Sensors; + +namespace WorkingWithMaps.Views.Code; + +public class GeocoderPageCode : ContentPage +{ + Label l = new Label(); + + public GeocoderPageCode() + { + Title = "Geocoder demo"; + + var b1 = new Button { Text = "Reverse geocode '37.808, -122.432'" }; + b1.Clicked += async (sender, e) => + { + Location fortMasonLocation = new Location(37.8044866, -122.4324132); + IEnumerable possibleAddresses = await Geocoding.Default.GetPlacemarksAsync(fortMasonLocation); + foreach (var a in possibleAddresses) + { + l.Text += a + "\n"; + } + }; + + var b2 = new Button { Text = "Geocode '394 Pacific Ave'" }; + b2.Clicked += async (sender, e) => + { + var address = "394 Pacific Ave, San Francisco, California"; + IEnumerable approximateLocations = await Geocoding.Default.GetLocationsAsync(address); + foreach (var p in approximateLocations) + { + l.Text += p.Latitude + ", " + p.Longitude + "\n"; + } + }; + + StackLayout sl = new StackLayout { Padding = new Thickness(0, 20, 0, 0) }; + sl.Add(b2); + sl.Add(b1); + sl.Add(l); + Content = sl; + } +} \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs new file mode 100644 index 0000000..8abbaa2 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapAppPageCode.cs @@ -0,0 +1,71 @@ +namespace WorkingWithMaps.Views.Code; + +public class MapAppPageCode : ContentPage +{ + // WARNING: when adding latitude/longitude values be careful of localization. + // European (and other countries) use a comma as the separator, which will break the request + public MapAppPageCode() + { + Title = "Native map app demo"; + + var l = new Label + { + Text = "These buttons leave the current app and open the built-in Maps app for the platform" + }; + + var openLocation = new Button + { + Text = "Open location using built-in Maps app" + }; + openLocation.Clicked += async (sender, e) => + { + if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst) + { + //https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html + await Launcher.OpenAsync("http://maps.apple.com/?q=394+Pacific+Ave+San+Francisco+CA"); + } + else if (DeviceInfo.Current.Platform == DevicePlatform.Android) + { + // opens the Maps app directly + await Launcher.OpenAsync("geo:0,0?q=394+Pacific+Ave+San+Francisco+CA"); + } + else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) + { + await Launcher.OpenAsync("bingmaps:?where=394 Pacific Ave San Francisco CA"); + } + }; + + var openDirections = new Button + { + Text = "Get directions using built-in Maps app" + }; + openDirections.Clicked += async (sender, e) => + { + if (DeviceInfo.Current.Platform == DevicePlatform.iOS || DeviceInfo.Current.Platform == DevicePlatform.MacCatalyst) + { + //https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/MapLinks/MapLinks.html + await Launcher.OpenAsync("http://maps.apple.com/?daddr=San+Francisco,+CA&saddr=cupertino"); + } + else if (DeviceInfo.Current.Platform == DevicePlatform.Android) + { + // opens the 'task chooser' so the user can pick Maps, Chrome or other mapping app + await Launcher.OpenAsync("http://maps.google.com/?daddr=San+Francisco,+CA&saddr=Mountain+View"); + } + else if (DeviceInfo.Current.Platform == DevicePlatform.WinUI) + { + await Launcher.OpenAsync("bingmaps:?rtp=adr.394 Pacific Ave San Francisco CA~adr.One Microsoft Way Redmond WA 98052"); + } + }; + + StackLayout sl = new StackLayout + { + Padding = new Thickness(5, 20, 5, 0) , + HorizontalOptions = LayoutOptions.Fill + }; + sl.Add(l); + sl.Add(openLocation); + sl.Add(openDirections); + + Content = sl; + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs new file mode 100644 index 0000000..03150c2 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapRegionPageCode.cs @@ -0,0 +1,22 @@ +using Microsoft.Maui.Maps; +using Map = Microsoft.Maui.Controls.Maps.Map; + +namespace WorkingWithMaps.Views.Code; + +public class MapRegionPageCode : ContentPage +{ + public MapRegionPageCode() + { + Title = "Map region demo"; + + Location location = new Location(36.9628066, -122.0194722); + MapSpan mapSpan = new MapSpan(location, 0.01, 0.01); + //MapSpan mapSpan = MapSpan.FromCenterAndRadius(position, Distance.FromKilometers(0.444)); + + Map map = new Map(mapSpan); + + StackLayout sl = new StackLayout { Margin = new Thickness(10) }; + sl.Add(map); + Content = sl; + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs new file mode 100644 index 0000000..53b1ff7 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/MapTypesPageCode.cs @@ -0,0 +1,71 @@ +using Microsoft.Maui.Maps; +using Map = Microsoft.Maui.Controls.Maps.Map; + +namespace WorkingWithMaps.Views.Code; + +public class MapTypesPageCode : ContentPage +{ + Map map; + public MapTypesPageCode() + { + Title = "Map types demo"; + + map = new Map(); + + // Create a Slider for zoom + Slider slider = new Slider(1, 18, 12) + { + Margin = new Thickness(20, 0, 20, 0) + }; + slider.ValueChanged += (sender, e) => + { + double zoomLevel = e.NewValue; // between 1 and 18 + double latlongDegrees = 360 / Math.Pow(2, zoomLevel); + if (map.VisibleRegion != null) + { + map.MoveToRegion(new MapSpan(map.VisibleRegion.Center, latlongDegrees, latlongDegrees)); + } + }; + + // Create buttons + Button streetButton = new Button { Text = "Street" }; + Button satelliteButton = new Button { Text = "Satellite" }; + Button hybridButton = new Button { Text = "Hybrid" }; + + streetButton.Clicked += OnButtonClicked; + satelliteButton.Clicked += OnButtonClicked; + hybridButton.Clicked += OnButtonClicked; + + StackLayout buttons = new StackLayout + { + Spacing = 30, + HorizontalOptions = LayoutOptions.Center, + Orientation = StackOrientation.Horizontal, + Children = { streetButton, satelliteButton, hybridButton } + }; + + // Build the page + StackLayout stackLayout = new StackLayout(); + stackLayout.Add(map); + stackLayout.Add(slider); + stackLayout.Add(buttons); + Content = stackLayout; + } + + void OnButtonClicked(object sender, EventArgs e) + { + Button button = sender as Button; + switch (button.Text) + { + case "Street": + map.MapType = MapType.Street; + break; + case "Satellite": + map.MapType = MapType.Satellite; + break; + case "Hybrid": + map.MapType = MapType.Hybrid; + break; + } + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs new file mode 100644 index 0000000..3cd2d38 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PinPageCode.cs @@ -0,0 +1,68 @@ +using Microsoft.Maui.Controls.Maps; +using Microsoft.Maui.Maps; +using Map = Microsoft.Maui.Controls.Maps.Map; + +namespace WorkingWithMaps.Views.Code; + +public class PinPageCode : ContentPage +{ + public PinPageCode() + { + Title = "Pins demo"; + + Location location = new Location(36.9628066, -122.0194722); + MapSpan mapSpan = new MapSpan(location, 0.01, 0.01); + + Map map = new Map(mapSpan); + + Pin pin = new Pin + { + Label = "Santa Cruz", + Address = "The city with a boardwalk", + Type = PinType.Place, + Location = location + }; + map.Pins.Add(pin); + + Button button = new Button { Text = "Add more pins" }; + button.Clicked += (sender, e) => + { + Pin boardwalkPin = new Pin + { + Location = new Location(36.9641949, -122.0177232), + Label = "Boardwalk", + Address = "Santa Cruz", + Type = PinType.Place + }; + + boardwalkPin.MarkerClicked += async (s, args) => + { + args.HideInfoWindow = true; + string pinName = ((Pin)s).Label; + await DisplayAlert("Pin Clicked", $"{pinName} was clicked.", "Ok"); + }; + + Pin wharfPin = new Pin + { + Location = new Location(36.9571571, -122.0173544), + Label = "Wharf", + Address = "Santa Cruz", + Type = PinType.Place + }; + + wharfPin.InfoWindowClicked += async (s, args) => + { + string pinName = ((Pin)s).Label; + await DisplayAlert("Info Window Clicked", $"The info window was clicked for {pinName}.", "Ok"); + }; + + map.Pins.Add(boardwalkPin); + map.Pins.Add(wharfPin); + }; + + StackLayout sl = new StackLayout { Margin = new Thickness(10) }; + sl.Add(map); + sl.Add(button); + Content = sl; + } +} diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs new file mode 100644 index 0000000..508c0c8 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/Code/PolygonsPageCode.cs @@ -0,0 +1,134 @@ +using Microsoft.Maui.Controls.Maps; +using Microsoft.Maui.Maps; +using Map = Microsoft.Maui.Controls.Maps.Map; + +namespace WorkingWithMaps.Views.Code; + +public class PolygonsPageCode : ContentPage +{ + Map map; + Polyline interstateBridge; + Polygon msWest; + Polygon msEast; + + public PolygonsPageCode() + { + Title = "Polygon/Polyline Code demo"; + + map = new Map(); + + Button polygonButton = new Button + { + Text = "Show Campus (Polygons)" + }; + polygonButton.Clicked += AddPolygonsClicked; + + Button polylineButton = new Button + { + Text = "Show Access Road (Polyline)" + }; + polylineButton.Clicked += AddPolylineClicked; + + Button clearButton = new Button + { + Text = "Clear All" + }; + clearButton.Clicked += ClearClicked; + + msWest = new Polygon + { + StrokeColor = Color.FromArgb("#FF9900"), + StrokeWidth = 8, + FillColor = Color.FromArgb("#88FF9900"), + Geopath = + { + new Location(47.6458676, -122.1356007), + new Location(47.6458097, -122.142789), + new Location(47.6367593, -122.1428104), + new Location(47.6368027, -122.1398707), + new Location(47.6380172, -122.1376177), + new Location(47.640663, -122.1352359), + new Location(47.6426148, -122.1347209), + new Location(47.6458676, -122.1356007) + } + }; + + msEast = new Polygon + { + StrokeColor = Color.FromArgb("#1BA1E2"), + StrokeWidth = 8, + FillColor = Color.FromArgb("#881BA1E2"), + Geopath = + { + new Location(47.6368678, -122.137305), + new Location(47.6368894, -122.134655), + new Location(47.6359424, -122.134655), + new Location(47.6359496, -122.1325521), + new Location(47.6424124, -122.1325199), + new Location(47.642463, -122.1338932), + new Location(47.6406414, -122.1344833), + new Location(47.6384943, -122.1361248), + new Location(47.6372943, -122.1376912), + new Location(47.6368678, -122.137305), + } + }; + + interstateBridge = new Polyline + { + StrokeColor = Colors.Black, + StrokeWidth = 12, + Geopath = + { + new Location(47.6381401, -122.1317367), + new Location(47.6381473, -122.1350841), + new Location(47.6382847, -122.1353094), + new Location(47.6384582, -122.1354703), + new Location(47.6401136, -122.1360819), + new Location(47.6403883, -122.1364681), + new Location(47.6407426, -122.1377019), + new Location(47.6412558, -122.1404056), + new Location(47.6414148, -122.1418647), + new Location(47.6414654, -122.1432702) + } + }; + + StackLayout sl = new StackLayout(); + sl.Add(map); + sl.Add(polygonButton); + sl.Add(polylineButton); + sl.Add(clearButton); + Content = sl; + + map.MoveToRegion( + MapSpan.FromCenterAndRadius( + new Location(47.640663, -122.1376177), Distance.FromMiles(1))); + } + + void AddPolylineClicked(object sender, EventArgs e) + { + if (!map.MapElements.Contains(interstateBridge)) + { + map.MapElements.Add(interstateBridge); + } + } + + void AddPolygonsClicked(object sender, EventArgs e) + { + if (!map.MapElements.Contains(msWest)) + { + map.MapElements.Add(msWest); + } + + if (!map.MapElements.Contains(msEast)) + { + map.MapElements.Add(msEast); + } + } + + void ClearClicked(object sender, EventArgs e) + { + map.MapElements.Remove(msWest); + map.MapElements.Remove(msEast); + map.MapElements.Remove(interstateBridge); + } +} \ No newline at end of file diff --git a/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml new file mode 100644 index 0000000..70b29e9 --- /dev/null +++ b/LotsOfPolylinesRepro/WorkingWithMaps/Views/GeocoderPage.xaml @@ -0,0 +1,16 @@ + + + +