mirror of
https://github.com/ClemensFischer/XAML-Map-Control.git
synced 2025-12-06 07:12:04 +01:00
Added MapBase.MapLayerItemsSource property
This commit is contained in:
parent
0b5d1e439f
commit
2194f08a74
241
MapControl/Shared/MapBase.MapLayer.cs
Normal file
241
MapControl/Shared/MapBase.MapLayer.cs
Normal file
|
|
@ -0,0 +1,241 @@
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
#if WPF
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Threading;
|
||||||
|
#elif UWP
|
||||||
|
using Windows.UI.Xaml;
|
||||||
|
using Windows.UI.Xaml.Controls;
|
||||||
|
using Windows.UI.Xaml.Media;
|
||||||
|
#elif WINUI
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public interface IMapLayer : IMapElement
|
||||||
|
{
|
||||||
|
Brush MapBackground { get; }
|
||||||
|
Brush MapForeground { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class MapBase
|
||||||
|
{
|
||||||
|
public static readonly DependencyProperty MapLayerProperty =
|
||||||
|
DependencyPropertyHelper.Register<MapBase, FrameworkElement>(nameof(MapLayer), null,
|
||||||
|
(map, oldValue, newValue) => map.MapLayerPropertyChanged(oldValue, newValue));
|
||||||
|
|
||||||
|
public static readonly DependencyProperty MapLayerItemsSourceProperty =
|
||||||
|
DependencyPropertyHelper.Register<MapBase, IEnumerable>(nameof(MapLayerItemsSource), null,
|
||||||
|
(map, oldValue, newValue) => map.MapLayerItemsSourcePropertyChanged(oldValue, newValue));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the base map layer, which is added as first element to the Children collection.
|
||||||
|
/// 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.
|
||||||
|
/// </summary>
|
||||||
|
public FrameworkElement MapLayer
|
||||||
|
{
|
||||||
|
get => (FrameworkElement)GetValue(MapLayerProperty);
|
||||||
|
set => SetValue(MapLayerProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable MapLayerItemsSource
|
||||||
|
{
|
||||||
|
get => (IEnumerable)GetValue(MapLayerItemsSourceProperty);
|
||||||
|
set => SetValue(MapLayerItemsSourceProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapLayerPropertyChanged(FrameworkElement oldLayer, FrameworkElement newLayer)
|
||||||
|
{
|
||||||
|
if (oldLayer != null)
|
||||||
|
{
|
||||||
|
if (Children.Count > 0 && Children[0] == oldLayer)
|
||||||
|
{
|
||||||
|
Children.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldLayer is IMapLayer mapLayer)
|
||||||
|
{
|
||||||
|
if (mapLayer.MapBackground != null)
|
||||||
|
{
|
||||||
|
ClearValue(BackgroundProperty);
|
||||||
|
}
|
||||||
|
if (mapLayer.MapForeground != null)
|
||||||
|
{
|
||||||
|
ClearValue(ForegroundProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLayer != null)
|
||||||
|
{
|
||||||
|
if (Children.Count == 0 || Children[0] != newLayer)
|
||||||
|
{
|
||||||
|
Children.Insert(0, newLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newLayer is IMapLayer mapLayer)
|
||||||
|
{
|
||||||
|
if (mapLayer.MapBackground != null)
|
||||||
|
{
|
||||||
|
Background = mapLayer.MapBackground;
|
||||||
|
}
|
||||||
|
if (mapLayer.MapForeground != null)
|
||||||
|
{
|
||||||
|
Foreground = mapLayer.MapForeground;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapLayerItemsSourcePropertyChanged(IEnumerable oldItems, IEnumerable newItems)
|
||||||
|
{
|
||||||
|
if (oldItems != null)
|
||||||
|
{
|
||||||
|
if (oldItems is INotifyCollectionChanged incc)
|
||||||
|
{
|
||||||
|
incc.CollectionChanged -= MapLayerItemsSourceCollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveMapLayers(oldItems, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newItems != null)
|
||||||
|
{
|
||||||
|
if (newItems is INotifyCollectionChanged incc)
|
||||||
|
{
|
||||||
|
incc.CollectionChanged += MapLayerItemsSourceCollectionChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddMapLayers(newItems, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MapLayerItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||||
|
{
|
||||||
|
switch (e.Action)
|
||||||
|
{
|
||||||
|
case NotifyCollectionChangedAction.Add:
|
||||||
|
AddMapLayers(e.NewItems, e.NewStartingIndex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotifyCollectionChangedAction.Remove:
|
||||||
|
RemoveMapLayers(e.OldItems, e.OldStartingIndex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotifyCollectionChangedAction.Replace:
|
||||||
|
RemoveMapLayers(e.OldItems, e.OldStartingIndex);
|
||||||
|
AddMapLayers(e.NewItems, e.NewStartingIndex);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotifyCollectionChangedAction.Reset:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddMapLayers(IEnumerable items, int index)
|
||||||
|
{
|
||||||
|
var mapLayers = items.Cast<object>().Select(CreateMapLayer).ToList();
|
||||||
|
#if WPF
|
||||||
|
// Execute at DispatcherPriority.DataBind to ensure that all bindings are evaluated.
|
||||||
|
Dispatcher.Invoke(() => AddMapLayers(mapLayers, index), DispatcherPriority.DataBind);
|
||||||
|
#else
|
||||||
|
AddMapLayers(mapLayers, index);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AddMapLayers(IEnumerable<FrameworkElement> mapLayers, int index)
|
||||||
|
{
|
||||||
|
foreach (var mapLayer in mapLayers)
|
||||||
|
{
|
||||||
|
Children.Insert(index, mapLayer);
|
||||||
|
|
||||||
|
if (index++ == 0)
|
||||||
|
{
|
||||||
|
MapLayer = mapLayer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RemoveMapLayers(IEnumerable items, int index)
|
||||||
|
{
|
||||||
|
Children.RemoveRange(index, items.Cast<object>().Count());
|
||||||
|
|
||||||
|
if (index == 0)
|
||||||
|
{
|
||||||
|
MapLayer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FrameworkElement CreateMapLayer(object item)
|
||||||
|
{
|
||||||
|
FrameworkElement mapLayer = null;
|
||||||
|
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
mapLayer = item as FrameworkElement ?? TryLoadDataTemplate(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapLayer ?? new MapControl.MapPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private FrameworkElement TryLoadDataTemplate(object item)
|
||||||
|
{
|
||||||
|
FrameworkElement element = null;
|
||||||
|
#if AVALONIA
|
||||||
|
if (this.TryFindResource(item.GetType().FullName, out object value) &&
|
||||||
|
value is Avalonia.Markup.Xaml.Templates.DataTemplate template)
|
||||||
|
{
|
||||||
|
element = template.Build(item);
|
||||||
|
}
|
||||||
|
#elif WPF
|
||||||
|
if (TryFindResource(new DataTemplateKey(item.GetType())) is DataTemplate template)
|
||||||
|
{
|
||||||
|
element = (FrameworkElement)template.LoadContent();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (this.TryFindResource(item.GetType().FullName) is DataTemplate template)
|
||||||
|
{
|
||||||
|
element = (FrameworkElement)template.LoadContent();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (element != null)
|
||||||
|
{
|
||||||
|
element.DataContext = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if UWP || WINUI
|
||||||
|
internal static class MapBaseExtensions
|
||||||
|
{
|
||||||
|
public static void RemoveRange(this UIElementCollection elements, int index, int count)
|
||||||
|
{
|
||||||
|
while (--count >= 0)
|
||||||
|
{
|
||||||
|
elements.RemoveAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
@ -12,12 +12,6 @@ using Microsoft.UI.Xaml.Media;
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
public interface IMapLayer : IMapElement
|
|
||||||
{
|
|
||||||
Brush MapBackground { get; }
|
|
||||||
Brush MapForeground { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The map control. Displays map content provided by one or more tile or image layers,
|
/// The map control. Displays map content provided by one or more tile or image layers,
|
||||||
/// such as MapTileLayerBase or MapImageLayer instances.
|
/// such as MapTileLayerBase or MapImageLayer instances.
|
||||||
|
|
@ -42,10 +36,6 @@ namespace MapControl
|
||||||
public static readonly DependencyProperty AnimationDurationProperty =
|
public static readonly DependencyProperty AnimationDurationProperty =
|
||||||
DependencyPropertyHelper.Register<MapBase, TimeSpan>(nameof(AnimationDuration), TimeSpan.FromSeconds(0.3));
|
DependencyPropertyHelper.Register<MapBase, TimeSpan>(nameof(AnimationDuration), TimeSpan.FromSeconds(0.3));
|
||||||
|
|
||||||
public static readonly DependencyProperty MapLayerProperty =
|
|
||||||
DependencyPropertyHelper.Register<MapBase, FrameworkElement>(nameof(MapLayer), null,
|
|
||||||
(map, oldValue, newValue) => map.MapLayerPropertyChanged(oldValue, newValue));
|
|
||||||
|
|
||||||
public static readonly DependencyProperty MapProjectionProperty =
|
public static readonly DependencyProperty MapProjectionProperty =
|
||||||
DependencyPropertyHelper.Register<MapBase, MapProjection>(nameof(MapProjection), new WebMercatorProjection(),
|
DependencyPropertyHelper.Register<MapBase, MapProjection>(nameof(MapProjection), new WebMercatorProjection(),
|
||||||
(map, oldValue, newValue) => map.MapProjectionPropertyChanged(newValue));
|
(map, oldValue, newValue) => map.MapProjectionPropertyChanged(newValue));
|
||||||
|
|
@ -84,17 +74,6 @@ namespace MapControl
|
||||||
set => SetValue(AnimationDurationProperty, value);
|
set => SetValue(AnimationDurationProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the base map layer, which is added as first element to the Children collection.
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
public FrameworkElement MapLayer
|
|
||||||
{
|
|
||||||
get => (FrameworkElement)GetValue(MapLayerProperty);
|
|
||||||
set => SetValue(MapLayerProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the MapProjection used by the map control.
|
/// Gets or sets the MapProjection used by the map control.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -440,49 +419,6 @@ namespace MapControl
|
||||||
internalPropertyChange = false;
|
internalPropertyChange = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapLayerPropertyChanged(FrameworkElement oldLayer, FrameworkElement newLayer)
|
|
||||||
{
|
|
||||||
if (oldLayer != null)
|
|
||||||
{
|
|
||||||
if (Children.Count > 0 && Children[0] == oldLayer)
|
|
||||||
{
|
|
||||||
Children.RemoveAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldLayer is IMapLayer mapLayer)
|
|
||||||
{
|
|
||||||
if (mapLayer.MapBackground != null)
|
|
||||||
{
|
|
||||||
ClearValue(BackgroundProperty);
|
|
||||||
}
|
|
||||||
if (mapLayer.MapForeground != null)
|
|
||||||
{
|
|
||||||
ClearValue(ForegroundProperty);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newLayer != null)
|
|
||||||
{
|
|
||||||
if (Children.Count == 0 || Children[0] != newLayer)
|
|
||||||
{
|
|
||||||
Children.Insert(0, newLayer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newLayer is IMapLayer mapLayer)
|
|
||||||
{
|
|
||||||
if (mapLayer.MapBackground != null)
|
|
||||||
{
|
|
||||||
Background = mapLayer.MapBackground;
|
|
||||||
}
|
|
||||||
if (mapLayer.MapForeground != null)
|
|
||||||
{
|
|
||||||
Foreground = mapLayer.MapForeground;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MapProjectionPropertyChanged(MapProjection projection)
|
private void MapProjectionPropertyChanged(MapProjection projection)
|
||||||
{
|
{
|
||||||
maxLatitude = 90d;
|
maxLatitude = 90d;
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,11 @@ namespace MapControl
|
||||||
{
|
{
|
||||||
mapElement.ParentMap = newValue;
|
mapElement.ParentMap = newValue;
|
||||||
}
|
}
|
||||||
},
|
#if UWP || WINUI
|
||||||
true); // inherits
|
});
|
||||||
|
#else
|
||||||
|
}, true); // inherits
|
||||||
|
#endif
|
||||||
|
|
||||||
public MapPanel()
|
public MapPanel()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,9 @@
|
||||||
<Compile Include="..\Shared\MapBase.cs">
|
<Compile Include="..\Shared\MapBase.cs">
|
||||||
<Link>MapBase.cs</Link>
|
<Link>MapBase.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\Shared\MapBase.MapLayer.cs">
|
||||||
|
<Link>MapBase.MapLayer.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\Shared\MapBorderPanel.cs">
|
<Compile Include="..\Shared\MapBorderPanel.cs">
|
||||||
<Link>MapBorderPanel.cs</Link>
|
<Link>MapBorderPanel.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
@ -281,6 +284,9 @@
|
||||||
<Compile Include="..\WinUI\Tile.WinUI.cs">
|
<Compile Include="..\WinUI\Tile.WinUI.cs">
|
||||||
<Link>Tile.WinUI.cs</Link>
|
<Link>Tile.WinUI.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="..\WinUI\TileSourceConverter.cs">
|
||||||
|
<Link>TileSourceConverter.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="TileImageLoader.UWP.cs" />
|
<Compile Include="TileImageLoader.UWP.cs" />
|
||||||
<EmbeddedResource Include="Properties\MapControl.UWP.rd.xml" />
|
<EmbeddedResource Include="Properties\MapControl.UWP.rd.xml" />
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ using Windows.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#pragma warning disable IDE0060 // Remove unused parameter
|
|
||||||
|
|
||||||
namespace MapControl
|
namespace MapControl
|
||||||
{
|
{
|
||||||
public static class DependencyPropertyHelper
|
public static class DependencyPropertyHelper
|
||||||
|
|
@ -15,8 +13,7 @@ namespace MapControl
|
||||||
string name,
|
string name,
|
||||||
Type ownerType,
|
Type ownerType,
|
||||||
TValue defaultValue = default,
|
TValue defaultValue = default,
|
||||||
Action<FrameworkElement, TValue, TValue> changed = null,
|
Action<FrameworkElement, TValue, TValue> changed = null)
|
||||||
bool inherits = false) // unused in WinUI/UWP
|
|
||||||
{
|
{
|
||||||
var metadata = changed == null
|
var metadata = changed == null
|
||||||
? new PropertyMetadata(defaultValue)
|
? new PropertyMetadata(defaultValue)
|
||||||
|
|
|
||||||
22
MapControl/WinUI/TileSourceConverter.cs
Normal file
22
MapControl/WinUI/TileSourceConverter.cs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
#if UWP
|
||||||
|
using Windows.UI.Xaml.Data;
|
||||||
|
#elif WINUI
|
||||||
|
using Microsoft.UI.Xaml.Data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace MapControl
|
||||||
|
{
|
||||||
|
public class TileSourceConverter : IValueConverter
|
||||||
|
{
|
||||||
|
public object Convert(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
return TileSource.Parse(value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue