MapLayer/MapLayerItemsSource

This commit is contained in:
ClemensFischer 2025-08-12 10:57:44 +02:00
parent 612c489eb9
commit bb47829cd3
4 changed files with 107 additions and 56 deletions

View file

@ -1,4 +1,6 @@
namespace MapControl using System.Collections.Generic;
namespace MapControl
{ {
public partial class MapPanel public partial class MapPanel
{ {
@ -13,6 +15,16 @@
protected Controls ChildElements => Children; protected Controls ChildElements => Children;
protected FrameworkElement GetChildElement(int index) => index < Children.Count ? Children[index] : null;
protected void InsertChildElement(int index, FrameworkElement element) => Children.Insert(index, element);
protected void InsertChildElements(int index, IEnumerable<FrameworkElement> elements) => Children.InsertRange(index, elements);
protected void RemoveChildElement(int index) => Children.RemoveAt(index);
protected void RemoveChildElements(int index, int count) => Children.RemoveRange(index, count);
static MapPanel() static MapPanel()
{ {
AffectsParentArrange<MapPanel>(LocationProperty, BoundingBoxProperty); AffectsParentArrange<MapPanel>(LocationProperty, BoundingBoxProperty);

View file

@ -8,11 +8,9 @@ using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
#elif UWP #elif UWP
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
#elif WINUI #elif WINUI
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media;
#endif #endif
@ -26,8 +24,11 @@ namespace MapControl
public partial class MapBase public partial class MapBase
{ {
private bool hasMapLayerBackground;
private bool hasMapLayerForeground;
public static readonly DependencyProperty MapLayerProperty = public static readonly DependencyProperty MapLayerProperty =
DependencyPropertyHelper.Register<MapBase, FrameworkElement>(nameof(MapLayer), null, DependencyPropertyHelper.Register<MapBase, object>(nameof(MapLayer), null,
(map, oldValue, newValue) => map.MapLayerPropertyChanged(oldValue, newValue)); (map, oldValue, newValue) => map.MapLayerPropertyChanged(oldValue, newValue));
public static readonly DependencyProperty MapLayerItemsSourceProperty = public static readonly DependencyProperty MapLayerItemsSourceProperty =
@ -39,9 +40,9 @@ namespace MapControl
/// If the layer implements IMapLayer (like MapTileLayer or MapImageLayer), its (non-null) MapBackground /// If the layer implements IMapLayer (like MapTileLayer or MapImageLayer), its (non-null) MapBackground
/// and MapForeground property values are used for the MapBase Background and Foreground properties. /// and MapForeground property values are used for the MapBase Background and Foreground properties.
/// </summary> /// </summary>
public FrameworkElement MapLayer public object MapLayer
{ {
get => (FrameworkElement)GetValue(MapLayerProperty); get => GetValue(MapLayerProperty);
set => SetValue(MapLayerProperty, value); set => SetValue(MapLayerProperty, value);
} }
@ -51,44 +52,52 @@ namespace MapControl
set => SetValue(MapLayerItemsSourceProperty, value); set => SetValue(MapLayerItemsSourceProperty, value);
} }
private void MapLayerPropertyChanged(FrameworkElement oldLayer, FrameworkElement newLayer) private void MapLayerPropertyChanged(object oldLayer, object newLayer)
{ {
var firstChild = GetChildElement(0);
if (oldLayer != null) if (oldLayer != null)
{ {
if (Children.Count > 0 && Children[0] == oldLayer) if (firstChild != null &&
(firstChild == oldLayer as FrameworkElement || firstChild.DataContext == oldLayer))
{ {
Children.RemoveAt(0); RemoveChildElement(0);
} }
if (oldLayer is IMapLayer mapLayer) if (hasMapLayerBackground)
{ {
if (mapLayer.MapBackground != null) ClearValue(BackgroundProperty);
{ }
ClearValue(BackgroundProperty);
} if (hasMapLayerForeground)
if (mapLayer.MapForeground != null) {
{ ClearValue(ForegroundProperty);
ClearValue(ForegroundProperty);
}
} }
} }
hasMapLayerBackground = false;
hasMapLayerForeground = false;
if (newLayer != null) if (newLayer != null)
{ {
if (Children.Count == 0 || Children[0] != newLayer) if (firstChild == null ||
firstChild != newLayer as FrameworkElement && firstChild.DataContext != newLayer)
{ {
Children.Insert(0, newLayer); InsertChildElement(0, GetMapLayer(newLayer));
} }
if (newLayer is IMapLayer mapLayer) if (GetChildElement(0) is IMapLayer mapLayer)
{ {
if (mapLayer.MapBackground != null) if (mapLayer.MapBackground != null)
{ {
Background = mapLayer.MapBackground; Background = mapLayer.MapBackground;
hasMapLayerBackground = true;
} }
if (mapLayer.MapForeground != null) if (mapLayer.MapForeground != null)
{ {
Foreground = mapLayer.MapForeground; Foreground = mapLayer.MapForeground;
hasMapLayerForeground = true;
} }
} }
} }
@ -144,31 +153,32 @@ namespace MapControl
private void AddMapLayers(IEnumerable items, int index) private void AddMapLayers(IEnumerable items, int index)
{ {
var mapLayers = items.Cast<object>().Select(CreateMapLayer).ToList(); var mapLayers = items.Cast<object>().Select(GetMapLayer).ToList();
if (mapLayers.Count > 0)
{
#if WPF #if WPF
// Execute at DispatcherPriority.DataBind to ensure that all bindings are evaluated. // Execute at DispatcherPriority.DataBind to ensure that all bindings are evaluated.
Dispatcher.Invoke(() => AddMapLayers(mapLayers, index), DispatcherPriority.DataBind); Dispatcher.Invoke(() => AddMapLayers(mapLayers, index), DispatcherPriority.DataBind);
#else #else
AddMapLayers(mapLayers, index); AddMapLayers(mapLayers, index);
#endif #endif
}
} }
private void AddMapLayers(IEnumerable<FrameworkElement> mapLayers, int index) private void AddMapLayers(List<FrameworkElement> mapLayers, int index)
{ {
foreach (var mapLayer in mapLayers) InsertChildElements(index, mapLayers);
{
Children.Insert(index, mapLayer);
if (index++ == 0) if (index == 0)
{ {
MapLayer = mapLayer; MapLayer = mapLayers[0];
}
} }
} }
private void RemoveMapLayers(IEnumerable items, int index) private void RemoveMapLayers(IEnumerable items, int index)
{ {
Children.RemoveRange(index, items.Cast<object>().Count()); RemoveChildElements(index, items.Cast<object>().Count());
if (index == 0) if (index == 0)
{ {
@ -176,7 +186,7 @@ namespace MapControl
} }
} }
private FrameworkElement CreateMapLayer(object item) private FrameworkElement GetMapLayer(object item)
{ {
FrameworkElement mapLayer = null; FrameworkElement mapLayer = null;
@ -185,7 +195,7 @@ namespace MapControl
mapLayer = item as FrameworkElement ?? TryLoadDataTemplate(item); mapLayer = item as FrameworkElement ?? TryLoadDataTemplate(item);
} }
return mapLayer ?? new MapControl.MapPanel(); return mapLayer ?? new MapTileLayer();
} }
private FrameworkElement TryLoadDataTemplate(object item) private FrameworkElement TryLoadDataTemplate(object item)
@ -203,7 +213,7 @@ namespace MapControl
element = (FrameworkElement)template.LoadContent(); element = (FrameworkElement)template.LoadContent();
} }
#else #else
if (this.TryFindResource(item.GetType().FullName) is DataTemplate template) if (TryFindResource(this, item.GetType().FullName) is DataTemplate template)
{ {
element = (FrameworkElement)template.LoadContent(); element = (FrameworkElement)template.LoadContent();
} }
@ -215,27 +225,16 @@ namespace MapControl
return element; return element;
} }
}
#if UWP || WINUI #if UWP || WINUI
internal static class MapBaseExtensions private static object TryFindResource(FrameworkElement element, object key)
{
public static void RemoveRange(this UIElementCollection elements, int index, int count)
{
while (--count >= 0)
{ {
elements.RemoveAt(index); return element.Resources.ContainsKey(key)
? element.Resources[key]
: element.Parent is FrameworkElement parent
? TryFindResource(parent, key)
: null;
} }
}
public static object TryFindResource(this FrameworkElement element, object key)
{
return element.Resources.ContainsKey(key)
? element.Resources[key]
: element.Parent is FrameworkElement parent
? TryFindResource(parent, key)
: null;
}
}
#endif #endif
}
} }

View file

@ -18,7 +18,23 @@ namespace MapControl
DependencyPropertyHelper.RegisterAttached<BoundingBox>("BoundingBox", typeof(MapPanel), null, DependencyPropertyHelper.RegisterAttached<BoundingBox>("BoundingBox", typeof(MapPanel), null,
FrameworkPropertyMetadataOptions.AffectsParentArrange); FrameworkPropertyMetadataOptions.AffectsParentArrange);
protected IEnumerable<FrameworkElement> ChildElements => InternalChildren.OfType<FrameworkElement>(); protected IEnumerable<FrameworkElement> ChildElements => Children.OfType<FrameworkElement>();
protected FrameworkElement GetChildElement(int index) => index < Children.Count ? (FrameworkElement)Children[index] : null;
protected void InsertChildElement(int index, FrameworkElement element) => Children.Insert(index, element);
protected void InsertChildElements(int index, IEnumerable<FrameworkElement> elements)
{
foreach (var element in elements)
{
Children.Insert(index++, element);
}
}
protected void RemoveChildElement(int index) => Children.RemoveAt(index);
protected void RemoveChildElements(int index, int count) => Children.RemoveRange(index, count);
public static MapBase GetParentMap(FrameworkElement element) public static MapBase GetParentMap(FrameworkElement element)
{ {

View file

@ -1,5 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Xml.Linq;
#if UWP #if UWP
using Windows.UI.Xaml; using Windows.UI.Xaml;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
@ -25,6 +27,28 @@ namespace MapControl
protected IEnumerable<FrameworkElement> ChildElements => Children.OfType<FrameworkElement>(); protected IEnumerable<FrameworkElement> ChildElements => Children.OfType<FrameworkElement>();
protected FrameworkElement GetChildElement(int index) => index < Children.Count ? (FrameworkElement)Children[index] : null;
protected void InsertChildElement(int index, FrameworkElement element) => Children.Insert(index, element);
protected void InsertChildElements(int index, IEnumerable<FrameworkElement> elements)
{
foreach (var element in elements)
{
Children.Insert(index++, element);
}
}
protected void RemoveChildElement(int index) => Children.RemoveAt(index);
protected void RemoveChildElements(int index, int count)
{
while (--count >= 0)
{
RemoveChildElement(index);
}
}
public static void InitMapElement(FrameworkElement element) public static void InitMapElement(FrameworkElement element)
{ {
// Workaround for missing property value inheritance. // Workaround for missing property value inheritance.