Skip to content

Commit 38ac72f

Browse files
jfversluisCopilot
andauthored
Add Pin.ShowInfoWindow() and Pin.HideInfoWindow() methods (#33985)
<!-- Please let the below note in for people that find this PR --> > [!NOTE] > Are you waiting for the changes in this PR to be merged? > It would be very helpful if you could [test the resulting artifacts](https://github.com/dotnet/maui/wiki/Testing-PR-Builds) from this PR and let us know in a comment if this change resolves your issue. Thank you! ## Description Adds the ability to programmatically show and hide map pin info windows/callouts, addressing a long-standing community request. Fixes #10601 ### API Changes **`Microsoft.Maui.Maps.IMap`** (Core): - `void ShowInfoWindow(IMapPin pin)` — Shows the info window for the specified pin - `void HideInfoWindow(IMapPin pin)` — Hides the info window for the specified pin **`Microsoft.Maui.Controls.Maps.Pin`** (Controls): - `void ShowInfoWindow()` — Shows the info window for this pin - `void HideInfoWindow()` — Hides the info window for this pin ### Implementation Details - **Android**: Uses `Marker.ShowInfoWindow()` / `Marker.HideInfoWindow()` via Google Maps SDK - **iOS/MacCatalyst**: Uses `MKMapView.SelectAnnotation()` / `MKMapView.DeselectAnnotation()` via MapKit - **Windows/Tizen/Standard**: Stub implementations (not supported) ### Bug Fix: Pin.Parent tracking Fixed a pre-existing bug where `Pin.Parent` was never set when pins were added to `Map.Pins`. The `PinsOnCollectionChanged` method now properly sets `pin.Parent = this` for new pins and `pin.Parent = null` for removed pins. This fix is required for `ShowInfoWindow()` to work (it needs to traverse to the parent Map to invoke the handler), but also fixes any other code path that relies on `Pin.Parent`. ### Testing - 4 unit tests added (ShowInfoWindow, HideInfoWindow, ShowInfoWindowRequiresParent, HideInfoWindowRequiresParent) - All 33 map unit tests pass - Manually verified on iOS, Android, and MacCatalyst Part of Maps Epic: #33787 --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent c0073ff commit 38ac72f

28 files changed

Lines changed: 314 additions & 0 deletions

File tree

src/Controls/Maps/src/HandlerImpl/Map.Impl.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ bool IMap.ClusterClicked(IReadOnlyList<IMapPin> pins, Location location)
2424

2525
void IMap.LongClicked(Location location) => MapLongClicked?.Invoke(this, new MapClickedEventArgs(location));
2626

27+
void IMap.ShowInfoWindow(IMapPin pin) => Handler?.Invoke(nameof(IMap.ShowInfoWindow), pin);
28+
29+
void IMap.HideInfoWindow(IMapPin pin) => Handler?.Invoke(nameof(IMap.HideInfoWindow), pin);
30+
2731
MapSpan? IMap.VisibleRegion
2832
{
2933
get

src/Controls/Maps/src/Map.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,22 @@ void PinsOnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
285285
throw new ArgumentException("Pin must have a Label to be added to a map");
286286
}
287287

288+
if (e.NewItems is not null)
289+
{
290+
foreach (Pin pin in e.NewItems)
291+
{
292+
pin.Parent = this;
293+
}
294+
}
295+
296+
if (e.OldItems is not null)
297+
{
298+
foreach (Pin pin in e.OldItems)
299+
{
300+
pin.Parent = null;
301+
}
302+
}
303+
288304
Handler?.UpdateValue(nameof(IMap.Pins));
289305
}
290306

src/Controls/Maps/src/Pin.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,30 @@ public bool SendInfoWindowClick()
212212
return args.HideInfoWindow;
213213
}
214214

215+
/// <summary>
216+
/// Shows the info window (callout) for this pin on the map.
217+
/// </summary>
218+
/// <remarks>The pin must be added to a <see cref="Map"/> for this method to have an effect.</remarks>
219+
public void ShowInfoWindow()
220+
{
221+
if (Parent is Map map)
222+
{
223+
map.Handler?.Invoke(nameof(IMap.ShowInfoWindow), this);
224+
}
225+
}
226+
227+
/// <summary>
228+
/// Hides the info window (callout) for this pin on the map.
229+
/// </summary>
230+
/// <remarks>The pin must be added to a <see cref="Map"/> for this method to have an effect.</remarks>
231+
public void HideInfoWindow()
232+
{
233+
if (Parent is Map map)
234+
{
235+
map.Handler?.Invoke(nameof(IMap.HideInfoWindow), this);
236+
}
237+
}
238+
215239
bool Equals(Pin other)
216240
{
217241
return string.Equals(Label, other.Label, StringComparison.Ordinal) &&

src/Controls/Maps/src/PublicAPI/net-android/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/net/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

src/Controls/Maps/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ Microsoft.Maui.Controls.Maps.MapElement.ZIndex.get -> int
1919
Microsoft.Maui.Controls.Maps.MapElement.ZIndex.set -> void
2020
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.get -> string!
2121
Microsoft.Maui.Controls.Maps.Pin.ClusteringIdentifier.set -> void
22+
Microsoft.Maui.Controls.Maps.Pin.HideInfoWindow() -> void
2223
Microsoft.Maui.Controls.Maps.Pin.ImageSource.get -> Microsoft.Maui.Controls.ImageSource?
2324
Microsoft.Maui.Controls.Maps.Pin.ImageSource.set -> void
25+
Microsoft.Maui.Controls.Maps.Pin.ShowInfoWindow() -> void
2426
Microsoft.Maui.Controls.Maps.Polygon.PolygonClicked -> System.EventHandler?
2527
Microsoft.Maui.Controls.Maps.Polyline.PolylineClicked -> System.EventHandler?
2628
const Microsoft.Maui.Controls.Maps.Pin.DefaultClusteringIdentifier = "maui_default_cluster" -> string!

0 commit comments

Comments
 (0)