2025-02-27 18:46:32 +01:00
|
|
|
|
using System;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#if WPF
|
|
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using System.Windows.Controls;
|
2021-11-17 23:17:11 +01:00
|
|
|
|
#elif UWP
|
2013-08-17 08:41:11 +02:00
|
|
|
|
using Windows.UI.Xaml;
|
|
|
|
|
|
using Windows.UI.Xaml.Controls;
|
2024-05-22 11:25:32 +02:00
|
|
|
|
#elif WINUI
|
|
|
|
|
|
using Microsoft.UI.Xaml;
|
|
|
|
|
|
using Microsoft.UI.Xaml.Controls;
|
2017-09-05 20:57:17 +02:00
|
|
|
|
#endif
|
2013-08-17 08:41:11 +02:00
|
|
|
|
|
2012-11-23 16:16:09 +01:00
|
|
|
|
namespace MapControl
|
|
|
|
|
|
{
|
2022-11-03 21:16:46 +01:00
|
|
|
|
/// <summary>
|
2024-07-22 18:06:27 +02:00
|
|
|
|
/// An ItemsControl with selectable items on a Map. Uses MapItem as item container.
|
2022-11-03 21:16:46 +01:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public partial class MapItemsControl : ListBox
|
|
|
|
|
|
{
|
2024-05-23 18:08:14 +02:00
|
|
|
|
public static readonly DependencyProperty LocationMemberPathProperty =
|
|
|
|
|
|
DependencyPropertyHelper.Register<MapItemsControl, string>(nameof(LocationMemberPath));
|
2021-01-11 22:35:17 +01:00
|
|
|
|
|
2021-01-13 00:08:55 +01:00
|
|
|
|
/// <summary>
|
2022-11-03 21:16:46 +01:00
|
|
|
|
/// Path to a source property for binding the Location property of MapItem containers.
|
2021-01-13 00:08:55 +01:00
|
|
|
|
/// </summary>
|
2021-01-11 22:35:17 +01:00
|
|
|
|
public string LocationMemberPath
|
|
|
|
|
|
{
|
2022-08-06 10:40:59 +02:00
|
|
|
|
get => (string)GetValue(LocationMemberPathProperty);
|
|
|
|
|
|
set => SetValue(LocationMemberPathProperty, value);
|
2021-01-11 22:35:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-10-21 22:18:16 +02:00
|
|
|
|
public void SelectItems(Predicate<object> predicate)
|
2018-11-13 21:35:48 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (SelectionMode == SelectionMode.Single)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new InvalidOperationException("SelectionMode must not be Single");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var item in Items)
|
|
|
|
|
|
{
|
|
|
|
|
|
var selected = predicate(item);
|
|
|
|
|
|
|
|
|
|
|
|
if (selected != SelectedItems.Contains(item))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (selected)
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedItems.Add(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SelectedItems.Remove(item);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-10-21 22:18:16 +02:00
|
|
|
|
public void SelectItemsByLocation(Predicate<Location> predicate)
|
2018-11-13 21:35:48 +01:00
|
|
|
|
{
|
|
|
|
|
|
SelectItems(item =>
|
|
|
|
|
|
{
|
2024-05-27 16:35:02 +02:00
|
|
|
|
var location = MapPanel.GetLocation(ContainerFromItem(item));
|
|
|
|
|
|
|
|
|
|
|
|
return location != null && predicate(location);
|
2018-11-13 21:35:48 +01:00
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2020-10-21 22:18:16 +02:00
|
|
|
|
public void SelectItemsByPosition(Predicate<Point> predicate)
|
2018-11-13 21:35:48 +01:00
|
|
|
|
{
|
|
|
|
|
|
SelectItems(item =>
|
|
|
|
|
|
{
|
2020-03-28 21:53:38 +01:00
|
|
|
|
var pos = MapPanel.GetViewPosition(ContainerFromItem(item));
|
2025-03-13 09:12:07 +01:00
|
|
|
|
|
2018-11-13 21:35:48 +01:00
|
|
|
|
return pos.HasValue && predicate(pos.Value);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public void SelectItemsInRect(Rect rect)
|
|
|
|
|
|
{
|
2025-03-13 09:12:07 +01:00
|
|
|
|
SelectItemsByPosition(rect.Contains);
|
2018-11-13 21:35:48 +01:00
|
|
|
|
}
|
2025-03-17 10:56:42 +01:00
|
|
|
|
|
2025-03-18 09:56:35 +01:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// Selects all items in a rectangular range between SelectedItem and the specified MapItem.
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
internal static void SelectItemsInRange(MapItem mapItem)
|
2025-03-17 10:56:42 +01:00
|
|
|
|
{
|
|
|
|
|
|
if (ItemsControlFromItemContainer(mapItem) is MapItemsControl mapItemsControl &&
|
|
|
|
|
|
mapItemsControl.SelectionMode != SelectionMode.Single)
|
|
|
|
|
|
{
|
|
|
|
|
|
var pos = MapPanel.GetViewPosition(mapItem);
|
|
|
|
|
|
|
|
|
|
|
|
if (pos.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
var xMin = pos.Value.X;
|
|
|
|
|
|
var xMax = pos.Value.X;
|
|
|
|
|
|
var yMin = pos.Value.Y;
|
|
|
|
|
|
var yMax = pos.Value.Y;
|
|
|
|
|
|
|
|
|
|
|
|
if (mapItemsControl.SelectedItem != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
var selectedMapItem = mapItemsControl.ContainerFromItem(mapItemsControl.SelectedItem);
|
|
|
|
|
|
|
|
|
|
|
|
if (selectedMapItem != mapItem)
|
|
|
|
|
|
{
|
|
|
|
|
|
pos = MapPanel.GetViewPosition(selectedMapItem);
|
|
|
|
|
|
|
|
|
|
|
|
if (pos.HasValue)
|
|
|
|
|
|
{
|
|
|
|
|
|
xMin = Math.Min(xMin, pos.Value.X);
|
|
|
|
|
|
xMax = Math.Max(xMax, pos.Value.X);
|
|
|
|
|
|
yMin = Math.Min(yMin, pos.Value.Y);
|
|
|
|
|
|
yMax = Math.Max(yMax, pos.Value.Y);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
mapItemsControl.SelectItemsInRect(new Rect(xMin, yMin, xMax - xMin, yMax - yMin));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2012-11-23 16:16:09 +01:00
|
|
|
|
}
|
2013-08-17 08:41:11 +02:00
|
|
|
|
}
|