postit: add rdv map marker and recenter action

This commit is contained in:
Paul Schneider 2026-09-06 17:05:18 +01:00
commit 9806bc0e0a
Signed by: notazof
GPG key ID: 1DD5D838E5343B06
2 changed files with 101 additions and 11 deletions

View file

@ -40,12 +40,20 @@
<TextBlock Grid.Row="6" Text="Adresse" VerticalAlignment="Center" Margin="0,0,12,8" /> <TextBlock Grid.Row="6" Text="Adresse" VerticalAlignment="Center" Margin="0,0,12,8" />
<TextBox Grid.Row="6" Grid.Column="1" Text="{Binding Address, Mode=TwoWay}" Margin="0,0,0,8" /> <TextBox Grid.Row="6" Grid.Column="1" Text="{Binding Address, Mode=TwoWay}" Margin="0,0,0,8" />
<Button Grid.Row="7" <Grid Grid.Row="7"
Grid.ColumnSpan="2" Grid.ColumnSpan="2"
ColumnDefinitions="Auto,12,Auto"
Margin="0,0,0,8">
<Button Grid.Column="0"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="0,0,0,8"
Content="Utiliser ma position" Content="Utiliser ma position"
Command="{Binding UseCurrentLocationCommand}" /> Command="{Binding UseCurrentLocationCommand}" />
<Button Grid.Column="2"
HorizontalAlignment="Left"
Content="Me localiser sur la carte"
Click="OnCenterCurrentLocationClicked"
IsEnabled="{Binding CanUseCurrentLocation}" />
</Grid>
<TextBlock Grid.Row="8" Text="Latitude" VerticalAlignment="Center" Margin="0,0,12,8" /> <TextBlock Grid.Row="8" Text="Latitude" VerticalAlignment="Center" Margin="0,0,12,8" />
<TextBox Grid.Row="8" Grid.Column="1" Text="{Binding Latitude, Mode=TwoWay}" PlaceholderText="Optionnel" Margin="0,0,0,8" /> <TextBox Grid.Row="8" Grid.Column="1" Text="{Binding Latitude, Mode=TwoWay}" PlaceholderText="Optionnel" Margin="0,0,0,8" />

View file

@ -1,7 +1,12 @@
using System.ComponentModel;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Mapsui; using Mapsui;
using Mapsui.Layers;
using Mapsui.Projections; using Mapsui.Projections;
using Mapsui.Styles;
using Mapsui.Tiling; using Mapsui.Tiling;
using Mapsui.UI.Avalonia; using Mapsui.UI.Avalonia;
using PostIt.ViewModels.Commands; using PostIt.ViewModels.Commands;
@ -10,7 +15,14 @@ namespace PostIt.Views.Commands;
public partial class RdvPage : ContentPage public partial class RdvPage : ContentPage
{ {
private const double DefaultLatitude = 48.8566;
private const double DefaultLongitude = 2.3522;
private const int DefaultZoomLevel = 4;
private const int SelectedZoomLevel = 13;
private MapControl? _locationMap; private MapControl? _locationMap;
private MemoryLayer? _selectionLayer;
private RdvViewModel? _currentViewModel;
public RdvPage() public RdvPage()
{ {
@ -31,15 +43,18 @@ public partial class RdvPage : ContentPage
var map = new Map(); var map = new Map();
map.Layers.Add(OpenStreetMap.CreateTileLayer()); map.Layers.Add(OpenStreetMap.CreateTileLayer());
_selectionLayer = CreateSelectionLayer();
map.Layers.Add(_selectionLayer);
_locationMap.Map = map; _locationMap.Map = map;
_locationMap.MapTapped += OnMapTapped; _locationMap.MapTapped += OnMapTapped;
DataContextChanged += OnDataContextChanged; DataContextChanged += OnDataContextChanged;
CenterFromViewModel(); AttachViewModel(DataContext as RdvViewModel);
} }
private void OnDataContextChanged(object? sender, System.EventArgs e) private void OnDataContextChanged(object? sender, System.EventArgs e)
{ {
AttachViewModel(DataContext as RdvViewModel);
CenterFromViewModel(); CenterFromViewModel();
} }
@ -50,24 +65,57 @@ public partial class RdvPage : ContentPage
var (longitude, latitude) = SphericalMercator.ToLonLat(e.WorldPosition.X, e.WorldPosition.Y); var (longitude, latitude) = SphericalMercator.ToLonLat(e.WorldPosition.X, e.WorldPosition.Y);
vm.ApplyLocationFromMap(latitude, longitude); vm.ApplyLocationFromMap(latitude, longitude);
CenterMap(latitude, longitude, zoomLevel: 13); UpdateMarkerFromViewModel();
CenterMap(latitude, longitude, zoomLevel: SelectedZoomLevel);
}
private async void OnCenterCurrentLocationClicked(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
if (DataContext is not RdvViewModel vm || !vm.CanUseCurrentLocation)
return;
await vm.UseCurrentLocationCommand.ExecuteAsync(null);
UpdateMarkerFromViewModel();
CenterFromViewModel();
}
private void AttachViewModel(RdvViewModel? vm)
{
if (_currentViewModel is not null)
_currentViewModel.PropertyChanged -= OnViewModelPropertyChanged;
_currentViewModel = vm;
if (_currentViewModel is not null)
_currentViewModel.PropertyChanged += OnViewModelPropertyChanged;
UpdateMarkerFromViewModel();
}
private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(RdvViewModel.Latitude)
|| e.PropertyName == nameof(RdvViewModel.Longitude))
{
UpdateMarkerFromViewModel();
}
} }
private void CenterFromViewModel() private void CenterFromViewModel()
{ {
if (DataContext is not RdvViewModel vm) if (DataContext is not RdvViewModel vm)
{ {
CenterMap(48.8566, 2.3522, zoomLevel: 4); CenterMap(DefaultLatitude, DefaultLongitude, zoomLevel: DefaultZoomLevel);
return; return;
} }
if (vm.Latitude.HasValue && vm.Longitude.HasValue) if (vm.Latitude.HasValue && vm.Longitude.HasValue)
{ {
CenterMap(vm.Latitude.Value, vm.Longitude.Value, zoomLevel: 13); CenterMap(vm.Latitude.Value, vm.Longitude.Value, zoomLevel: SelectedZoomLevel);
return; return;
} }
CenterMap(48.8566, 2.3522, zoomLevel: 4); CenterMap(DefaultLatitude, DefaultLongitude, zoomLevel: DefaultZoomLevel);
} }
private void CenterMap(double latitude, double longitude, int zoomLevel) private void CenterMap(double latitude, double longitude, int zoomLevel)
@ -79,4 +127,38 @@ public partial class RdvPage : ContentPage
_locationMap.Map.Navigator.CenterOn(x, y); _locationMap.Map.Navigator.CenterOn(x, y);
_locationMap.Map.Navigator.ZoomToLevel(zoomLevel); _locationMap.Map.Navigator.ZoomToLevel(zoomLevel);
} }
private void UpdateMarkerFromViewModel()
{
if (_selectionLayer is null)
return;
if (DataContext is not RdvViewModel vm
|| !vm.Latitude.HasValue
|| !vm.Longitude.HasValue)
{
_selectionLayer.Features = Enumerable.Empty<IFeature>();
_locationMap?.RefreshData(ChangeType.Discrete);
return;
}
var (x, y) = SphericalMercator.FromLonLat(vm.Longitude.Value, vm.Latitude.Value);
_selectionLayer.Features = new IFeature[] { new PointFeature(x, y) };
_locationMap?.RefreshData(ChangeType.Discrete);
}
private static MemoryLayer CreateSelectionLayer()
{
return new MemoryLayer("selected-location")
{
Style = new SymbolStyle
{
SymbolType = SymbolType.Ellipse,
Fill = new Brush(Color.Crimson),
Outline = new Pen(Color.White, 2),
SymbolScale = 0.9,
},
Features = Enumerable.Empty<IFeature>(),
};
}
} }