第02章 - 环境搭建与快速开始

第02章:环境搭建与快速开始

2.1 开发环境准备

2.1.1 系统要求

Mapsui 支持在多种操作系统上进行开发:

操作系统 支持版本 可开发的目标平台
Windows Windows 10/11 WPF, WinUI, Windows Forms, MAUI, Blazor, Avalonia
macOS macOS 11+ MAUI, Avalonia, iOS
Linux Ubuntu 20.04+ Avalonia, Blazor

2.1.2 开发工具

推荐使用以下开发工具:

工具 版本要求 说明
Visual Studio 2022 17.8+ Windows 上的首选 IDE
Visual Studio for Mac 最新版 macOS 开发
JetBrains Rider 2023.3+ 跨平台 IDE
VS Code 最新版 轻量级编辑器

2.1.3 .NET SDK 安装

Mapsui 需要 .NET 6.0 或更高版本。推荐使用最新的 LTS 版本:

# 检查已安装的 .NET 版本
dotnet --list-sdks

# 下载 .NET SDK (从 https://dotnet.microsoft.com/download)
# Windows: 运行安装程序
# macOS: brew install --cask dotnet-sdk
# Linux: 参考官方文档安装

2.1.4 工作负载安装

根据目标平台,需要安装相应的工作负载:

# MAUI 开发
dotnet workload install maui

# iOS 开发 (仅 macOS)
dotnet workload install ios

# Android 开发
dotnet workload install android

# Blazor WebAssembly
dotnet workload install wasm-tools

2.2 各平台快速入门

2.2.1 MAUI 应用

步骤 1: 创建新的 .NET MAUI 应用:

dotnet new maui -n MapsuiMauiApp
cd MapsuiMauiApp

步骤 2: 添加 Mapsui.Maui NuGet 包:

dotnet add package Mapsui.Maui

步骤 3: 修改 MauiProgram.cs,添加 SkiaSharp 初始化:

using SkiaSharp.Views.Maui.Controls.Hosting;

namespace MapsuiMauiApp;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .UseSkiaSharp()  // 关键:必须添加这行
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });

        return builder.Build();
    }
}

步骤 4: 修改 MainPage.xaml.cs

using Mapsui.UI.Maui;
using Mapsui.Tiling;

namespace MapsuiMauiApp;

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
        
        var mapControl = new MapControl();
        mapControl.Map?.Layers.Add(OpenStreetMap.CreateTileLayer());
        Content = mapControl;
    }
}

步骤 5: 运行应用:

dotnet build
dotnet run

2.2.2 Avalonia 应用

准备工作: 安装 Avalonia 模板:

dotnet new install Avalonia.Templates

步骤 1: 创建新的 Avalonia 项目:

dotnet new avalonia.app -o MapsuiAvaloniaApp
cd MapsuiAvaloniaApp

步骤 2: 添加 Mapsui.Avalonia NuGet 包:

dotnet add package Mapsui.Avalonia

步骤 3: 修改 MainWindow.axaml

<Window xmlns="https://github.com/avaloniaui"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:mapsui="clr-namespace:Mapsui.UI.Avalonia;assembly=Mapsui.UI.Avalonia"
        mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
        x:Class="MapsuiAvaloniaApp.MainWindow"
        Title="Mapsui Avalonia Demo">
    
    <mapsui:MapControl x:Name="MyMapControl" />
    
</Window>

步骤 4: 修改 MainWindow.axaml.cs

using Avalonia.Controls;
using Mapsui.Tiling;

namespace MapsuiAvaloniaApp;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        
        MyMapControl.Map?.Layers.Add(OpenStreetMap.CreateTileLayer());
    }
}

步骤 5: 运行应用:

dotnet run

2.2.3 Blazor 应用

步骤 1: 创建新的 Blazor WebAssembly 应用:

dotnet new blazorwasm -o MapsuiBlazorApp
cd MapsuiBlazorApp

步骤 2: 添加 Mapsui.Blazor NuGet 包:

dotnet add package Mapsui.Blazor

步骤 3: 修改 Pages/Home.razor(或 Pages/Index.razor):

@page "/"
@using Mapsui.UI.Blazor
@using Mapsui.Tiling

<div class="container">
    <div class="row">
        <div class="col border rounded p-2 canvas-container">
            <MapControlComponent @ref="_mapControl" />
        </div>
    </div>
</div>

<style>
    .canvas-container canvas {
        width: 100%;
        height: 80vh;
    }
</style>

@code {
    private MapControl? _mapControl;

    protected override void OnAfterRender(bool firstRender)
    {
        base.OnAfterRender(firstRender);
        
        if (firstRender)
        {
            _mapControl?.Map?.Layers.Add(OpenStreetMap.CreateTileLayer());
        }
    }
}

步骤 4: 运行应用:

dotnet run

故障排除: 如果文本无法正常显示,在项目文件中添加:

<ItemGroup>
    <PackageReference Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="2.8.2.3" GeneratePathProperty="true" />
    <NativeFileReference Include="$(PKGHarfBuzzSharp_NativeAssets_WebAssembly)\build\netstandard1.0\libHarfBuzzSharp.a\3.1.12\libHarfBuzzSharp.a" />
</ItemGroup>

2.2.4 WPF 应用

步骤 1: 创建新的 WPF 项目:

dotnet new wpf -n MapsuiWpfApp -f net9.0
cd MapsuiWpfApp

步骤 2: 添加 Mapsui 相关 NuGet 包:

dotnet add package Mapsui
dotnet add package Mapsui.Wpf

步骤 3: 修改 MainWindow.xaml

<Window x:Class="MapsuiWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mapsui="clr-namespace:Mapsui.UI.Wpf;assembly=Mapsui.UI.Wpf"
        Title="Mapsui WPF Demo" 
        Height="600" Width="800">
    <Grid>
        <mapsui:MapControl x:Name="mapControl" />
    </Grid>
</Window>

步骤 4: 修改 MainWindow.xaml.cs

using System.Windows;
using Mapsui;
using Mapsui.Tiling;

namespace MapsuiWpfApp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            
            var map = new Map();
            map.Layers.Add(OpenStreetMap.CreateTileLayer());
            mapControl.Map = map;
        }
    }
}

步骤 5: 运行应用:

dotnet run

2.2.5 WinUI 应用

步骤 1: 在 Visual Studio 中创建新的 'Blank App, Packaged (WinUI 3 in Desktop)' 项目。

步骤 2: 添加 Mapsui.WinUI NuGet 包:

dotnet add package Mapsui.WinUI

步骤 3: 修改 MainPage.xaml

<?xml version="1.0" encoding="utf-8"?>
<Page
    x:Class="MapsuiWinUIApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:winui="using:Mapsui.UI.WinUI">
    
    <Grid>
        <winui:MapControl x:Name="MyMap" 
                          VerticalAlignment="Stretch" 
                          HorizontalAlignment="Stretch" />
    </Grid>
</Page>

步骤 4: 修改 MainPage.xaml.cs

using Microsoft.UI.Xaml.Controls;
using Mapsui.Tiling;

namespace MapsuiWinUIApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            
            MyMap.Map.Layers.Add(OpenStreetMap.CreateTileLayer());
        }
    }
}

2.2.6 Windows Forms 应用

步骤 1: 创建新的 Windows Forms 项目:

dotnet new winforms -n MapsuiWinFormsApp -f net9.0
cd MapsuiWinFormsApp

步骤 2: 添加 Mapsui.WindowsForms NuGet 包:

dotnet add package Mapsui.WindowsForms

步骤 3: 修改 Form1.cs

using Mapsui.UI.WinForms;
using Mapsui.Tiling;

namespace MapsuiWinFormsApp
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            
            var mapControl = new MapControl
            {
                Dock = DockStyle.Fill
            };
            mapControl.Map.Layers.Add(OpenStreetMap.CreateTileLayer());
            
            Controls.Add(mapControl);
        }
    }
}

步骤 4: 运行应用:

dotnet run

2.2.7 Uno Platform 应用

准备工作: 参考 Uno Platform 入门指南 配置开发环境。

步骤 1: 在 Visual Studio 中创建新的 'Uno Platform App' 项目。

步骤 2: 为所有目标平台添加 Mapsui.Uno.WinUI NuGet 包:

dotnet add package Mapsui.Uno.WinUI

步骤 3: 修改 MainPage.xaml

<Page
    x:Class="MapsuiUnoApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mapsui="clr-namespace:Mapsui.UI.WinUI;assembly=Mapsui.UI.Uno.WinUI">
    
    <Grid>
        <mapsui:MapControl x:Name="MyMap" 
                           VerticalAlignment="Stretch" 
                           HorizontalAlignment="Stretch" />
    </Grid>
</Page>

步骤 4: 修改 MainPage.xaml.cs

using Windows.UI.Xaml.Controls;
using Mapsui.Tiling;

namespace MapsuiUnoApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            
            MyMap.Map.Layers.Add(OpenStreetMap.CreateTileLayer());
        }
    }
}

2.2.8 Eto Forms 应用

步骤 1: 创建新的 Eto.Forms 应用。

步骤 2: 将主项目的目标框架更新为 net9.0(Mapsui.Eto 需要 .NET 9.0+):

<PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
</PropertyGroup>

步骤 3: 添加 Mapsui.Eto NuGet 包:

dotnet add package Mapsui.Eto

步骤 4: 修改 MainForm.cs

using Eto.Forms;
using Mapsui.UI.Eto;
using Mapsui.Tiling;

namespace MapsuiEtoApp
{
    public class MainForm : Form
    {
        public MainForm()
        {
            Title = "Mapsui Eto Demo";
            ClientSize = new Eto.Drawing.Size(800, 600);
            
            var mapControl = new MapControl();
            mapControl.Map.Layers.Add(OpenStreetMap.CreateTileLayer());
            
            Content = mapControl;
        }
    }
}

2.2.9 .NET for Android 应用

步骤 1: 在 Visual Studio 中创建新的 'Blank App (Android)' 项目。

步骤 2: 添加 Mapsui.Android NuGet 包:

dotnet add package Mapsui.Android

步骤 3: 修改 Resources/layout/Main.axml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <Mapsui.UI.Android.MapControl
        android:id="@+id/mapcontrol"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
        
</LinearLayout>

步骤 4: 修改 MainActivity.cs

using Android.App;
using Android.OS;
using Mapsui;
using Mapsui.UI.Android;
using Mapsui.Tiling;

namespace MapsuiAndroidApp
{
    [Activity(Label = "@string/app_name", MainLauncher = true)]
    public class MainActivity : Activity
    {
        protected override void OnCreate(Bundle? savedInstanceState)
        {
            base.OnCreate(savedInstanceState);
            SetContentView(Resource.Layout.Main);

            var mapControl = FindViewById<MapControl>(Resource.Id.mapcontrol);
            if (mapControl != null)
            {
                var map = new Map();
                map.Layers.Add(OpenStreetMap.CreateTileLayer());
                mapControl.Map = map;
            }
        }
    }
}

2.2.10 .NET for iOS 应用

步骤 1: 在 Visual Studio for Mac 中创建新的 'Single View App' 项目。

步骤 2: 添加 Mapsui.iOS NuGet 包:

dotnet add package Mapsui.iOS

步骤 3: 修改 ViewController.cs

using UIKit;
using Mapsui;
using Mapsui.UI.iOS;
using Mapsui.Tiling;

namespace MapsuiiOSApp
{
    public partial class ViewController : UIViewController
    {
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            
            var mapControl = new MapControl(View!.Bounds);
            var map = new Map();
            map.Layers.Add(OpenStreetMap.CreateTileLayer());
            mapControl.Map = map;
            
            View = mapControl;
        }
    }
}

2.3 项目结构与配置

2.3.1 典型项目结构

一个标准的 Mapsui 应用项目结构如下:

MapsuiApp/
├── Properties/
│   └── launchSettings.json
├── Resources/              # 资源文件(图标、图片等)
│   ├── Images/
│   └── Styles/
├── Services/               # 服务类
│   ├── MapService.cs
│   └── DataService.cs
├── ViewModels/             # MVVM 视图模型
│   └── MainViewModel.cs
├── Views/                  # 视图/页面
│   └── MainView.xaml
├── Layers/                 # 自定义图层
│   └── CustomLayer.cs
├── Styles/                 # 自定义样式
│   └── MapStyles.cs
├── App.xaml
├── App.xaml.cs
├── Program.cs
└── MapsuiApp.csproj

2.3.2 NuGet 包配置

根据项目需求选择合适的 NuGet 包组合:

<ItemGroup>
    <!-- 核心包 -->
    <PackageReference Include="Mapsui" Version="5.*" />
    
    <!-- UI 框架特定包 (选择一个) -->
    <PackageReference Include="Mapsui.Wpf" Version="5.*" />
    <!-- 或 -->
    <PackageReference Include="Mapsui.Maui" Version="5.*" />
    
    <!-- 可选扩展 -->
    <PackageReference Include="Mapsui.Nts" Version="5.*" />
    <PackageReference Include="Mapsui.Extensions" Version="5.*" />
    <PackageReference Include="Mapsui.ArcGIS" Version="5.*" />
</ItemGroup>

2.3.3 基本配置

创建一个配置类来管理地图设置:

public static class MapConfiguration
{
    public static Map CreateDefaultMap()
    {
        var map = new Map
        {
            CRS = "EPSG:3857",  // Web Mercator
            BackColor = Color.FromString("#E0E0E0")
        };
        
        // 添加默认图层
        map.Layers.Add(OpenStreetMap.CreateTileLayer());
        
        // 添加默认小部件
        map.Widgets.Add(new Mapsui.Widgets.ScaleBar.ScaleBarWidget(map)
        {
            MarginX = 10,
            MarginY = 10
        });
        
        return map;
    }
}

2.4 第一个完整示例

2.4.1 创建带标注的地图应用

下面是一个完整的 WPF 示例,展示如何创建一个带有多个标注点的地图应用:

MainWindow.xaml:

<Window x:Class="MapsuiDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mapsui="clr-namespace:Mapsui.UI.Wpf;assembly=Mapsui.UI.Wpf"
        Title="Mapsui 示例应用" 
        Height="600" Width="900">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        
        <!-- 工具栏 -->
        <StackPanel Grid.Row="0" Orientation="Horizontal" Margin="5">
            <Button Content="添加点" Click="AddPoint_Click" Margin="5"/>
            <Button Content="清除" Click="Clear_Click" Margin="5"/>
            <Button Content="回到中国" Click="ZoomToChina_Click" Margin="5"/>
        </StackPanel>
        
        <!-- 地图控件 -->
        <mapsui:MapControl x:Name="mapControl" Grid.Row="1"/>
    </Grid>
</Window>

MainWindow.xaml.cs:

using System;
using System.Collections.Generic;
using System.Windows;
using Mapsui;
using Mapsui.Layers;
using Mapsui.Nts;
using Mapsui.Projections;
using Mapsui.Styles;
using Mapsui.Tiling;
using Mapsui.Widgets.ScaleBar;
using Mapsui.Widgets.Zoom;

namespace MapsuiDemo
{
    public partial class MainWindow : Window
    {
        private WritableLayer _pointLayer;
        private int _pointCount = 0;

        public MainWindow()
        {
            InitializeComponent();
            InitializeMap();
        }

        private void InitializeMap()
        {
            var map = new Map();
            
            // 添加 OpenStreetMap 底图
            map.Layers.Add(OpenStreetMap.CreateTileLayer());
            
            // 创建可写图层用于添加点
            _pointLayer = new WritableLayer
            {
                Name = "Points",
                Style = CreatePointStyle()
            };
            map.Layers.Add(_pointLayer);
            
            // 添加缩放按钮小部件
            map.Widgets.Add(new ZoomInOutWidget
            {
                MarginX = 20,
                MarginY = 20
            });
            
            // 添加比例尺小部件
            map.Widgets.Add(new ScaleBarWidget(map)
            {
                MarginX = 10,
                MarginY = 40
            });
            
            mapControl.Map = map;
            
            // 添加一些示例城市
            AddCityPoints();
            
            // 初始视图定位到中国
            ZoomToChina();
            
            // 处理地图点击事件
            mapControl.Map.Info += Map_Info;
        }

        private void AddCityPoints()
        {
            var cities = new[]
            {
                (Name: "北京", Lon: 116.4, Lat: 39.9),
                (Name: "上海", Lon: 121.5, Lat: 31.2),
                (Name: "广州", Lon: 113.3, Lat: 23.1),
                (Name: "深圳", Lon: 114.1, Lat: 22.5),
                (Name: "杭州", Lon: 120.2, Lat: 30.3),
                (Name: "成都", Lon: 104.1, Lat: 30.7)
            };

            foreach (var city in cities)
            {
                AddPoint(city.Lon, city.Lat, city.Name);
            }
        }

        private void AddPoint(double lon, double lat, string name)
        {
            var point = SphericalMercator.FromLonLat(lon, lat).ToMPoint();
            var feature = new PointFeature(point);
            feature["name"] = name;
            feature.Styles = new List<IStyle>
            {
                CreatePointStyle(),
                CreateLabelStyle(name)
            };
            
            _pointLayer.Add(feature);
            _pointLayer.DataHasChanged();
        }

        private static SymbolStyle CreatePointStyle()
        {
            return new SymbolStyle
            {
                SymbolScale = 0.5,
                Fill = new Brush(Color.Red),
                Outline = new Pen(Color.White, 2)
            };
        }

        private static LabelStyle CreateLabelStyle(string text)
        {
            return new LabelStyle
            {
                Text = text,
                ForeColor = Color.Black,
                BackColor = new Brush(new Color(255, 255, 255, 200)),
                Offset = new Offset(0, -25),
                Font = new Font { Size = 12 }
            };
        }

        private void AddPoint_Click(object sender, RoutedEventArgs e)
        {
            // 在随机位置添加点
            var random = new Random();
            var lon = 100 + random.NextDouble() * 35;  // 中国经度范围
            var lat = 20 + random.NextDouble() * 25;   // 中国纬度范围
            
            _pointCount++;
            AddPoint(lon, lat, $"点 {_pointCount}");
        }

        private void Clear_Click(object sender, RoutedEventArgs e)
        {
            _pointLayer.Clear();
            _pointLayer.DataHasChanged();
            _pointCount = 0;
        }

        private void ZoomToChina_Click(object sender, RoutedEventArgs e)
        {
            ZoomToChina();
        }

        private void ZoomToChina()
        {
            // 中国的边界范围(经纬度)
            var minLon = 73.0;
            var maxLon = 135.0;
            var minLat = 18.0;
            var maxLat = 54.0;
            
            // 转换为 Web Mercator 坐标
            var min = SphericalMercator.FromLonLat(minLon, minLat);
            var max = SphericalMercator.FromLonLat(maxLon, maxLat);
            
            // 缩放到中国范围
            mapControl.Map.Navigator.ZoomToBox(
                new MRect(min.X, min.Y, max.X, max.Y),
                MBoxFit.Fit
            );
        }

        private void Map_Info(object? sender, MapInfoEventArgs e)
        {
            if (e.MapInfo?.Feature != null)
            {
                var name = e.MapInfo.Feature["name"]?.ToString() ?? "未知";
                MessageBox.Show($"点击了: {name}", "地图信息");
            }
        }
    }
}

2.4.2 运行效果

运行上述代码后,您将看到:

  1. OpenStreetMap 底图
  2. 中国主要城市的标注点
  3. 缩放控制按钮
  4. 比例尺
  5. 点击标注点会显示城市名称

2.5 常见问题与解决方案

2.5.1 MAUI 应用崩溃

问题: 应用启动时崩溃,报错 Catastrophic failure (0x8000FFFF)Microsoft.Mapsui.Platform.HandlerNotFoundException

解决方案: 确保在 MauiProgram.cs 中添加了 .UseSkiaSharp()

builder.UseMauiApp<App>().UseSkiaSharp();

2.5.2 Blazor 文本不显示

问题: Blazor 应用中文本/标签无法正常显示。

解决方案: 在项目文件中添加 HarfBuzz 引用:

<ItemGroup>
    <PackageReference Include="HarfBuzzSharp.NativeAssets.WebAssembly" 
                      Version="2.8.2.3" 
                      GeneratePathProperty="true" />
    <NativeFileReference Include="$(PKGHarfBuzzSharp_NativeAssets_WebAssembly)\build\netstandard1.0\libHarfBuzzSharp.a\3.1.12\libHarfBuzzSharp.a" />
</ItemGroup>

2.5.3 地图不显示

问题: 地图控件显示但没有内容。

解决方案:

  1. 检查是否添加了图层
  2. 检查网络连接(在线瓦片需要网络)
  3. 检查是否正确设置了 Map 属性
// 确保正确设置
mapControl.Map = map;  // 而不是 mapControl.Map.Layers.Add(...)

2.5.4 坐标显示错误

问题: 添加的点位置不正确。

解决方案: 确保进行了正确的坐标转换:

// 如果使用经纬度,需要转换为 Web Mercator
var point = SphericalMercator.FromLonLat(lon, lat).ToMPoint();

2.5.5 Uno Platform 编译错误

问题: 遇到 Duplicate Attribute 错误。

解决方案:.csproj 文件中添加:

<Target Name="FilterAnalyzers" BeforeTargets="CoreCompile">
    <ItemGroup>
        <FilteredAnalyzer Include="@(Analyzer->Distinct())" />
        <Analyzer Remove="@(Analyzer)" />
        <Analyzer Include="@(FilteredAnalyzer)" />
    </ItemGroup>
</Target>

2.6 本章小结

本章详细介绍了 Mapsui 的环境搭建和各平台的快速入门:

  1. 开发环境准备:安装 .NET SDK、开发工具和必要的工作负载
  2. 各平台快速入门
    • MAUI、Avalonia、Blazor
    • WPF、WinUI、Windows Forms
    • Uno Platform、Eto Forms
    • .NET for Android、.NET for iOS
  3. 项目结构与配置:合理组织项目结构和 NuGet 包配置
  4. 完整示例:创建带标注的交互式地图应用
  5. 常见问题解决:针对各平台的常见问题提供解决方案

在下一章中,我们将深入探讨 Mapsui 的核心架构与组件设计。

2.7 思考与练习

  1. 在您最熟悉的平台上创建一个 Mapsui 应用并显示 OpenStreetMap。
  2. 尝试添加一个自定义的标注点到地图上。
  3. 修改示例代码,将底图更换为其他地图服务(如 BingMaps)。
  4. 实现一个功能:点击地图时在点击位置添加一个标注。
  5. 比较不同平台上 Mapsui 应用的性能差异。

posted @ 2026-01-09 00:40  我才是银古  阅读(30)  评论(0)    收藏  举报