diff --git a/MapControl/Shared/MapItemsControl.cs b/MapControl/Shared/MapItemsControl.cs index 1eb15978..5c5bae85 100644 --- a/MapControl/Shared/MapItemsControl.cs +++ b/MapControl/Shared/MapItemsControl.cs @@ -2,35 +2,23 @@ // © 2018 Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) +using System; #if WINDOWS_UWP +using Windows.Foundation; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; -using KeyEventArgs = Windows.UI.Xaml.Input.KeyRoutedEventArgs; #else using System.Windows; using System.Windows.Controls; -using System.Windows.Input; #endif namespace MapControl { - /// - /// Container class for an item in a MapItemsControl. - /// - public class MapItem : ListBoxItem - { - public MapItem() - { - DefaultStyleKey = typeof(MapItem); - - MapPanel.InitMapElement(this); - } - } /// /// Manages a collection of selectable items on a Map. /// - public class MapItemsControl : ListBox + public partial class MapItemsControl : ListBox { public MapItemsControl() { @@ -49,8 +37,102 @@ namespace MapControl return item is MapItem; } - protected override void OnKeyDown(KeyEventArgs e) + public void SelectItems(Func predicate) { + 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); + } + } + } + } + + public void SelectItemsByLocation(Func predicate) + { + SelectItems(item => + { + var loc = MapPanel.GetLocation(MapItemFromItem(item)); + return loc != null && predicate(loc); + }); + } + + public void SelectItemsByPosition(Func predicate) + { + SelectItems(item => + { + var pos = MapPanel.GetViewportPosition(MapItemFromItem(item)); + return pos.HasValue && predicate(pos.Value); + }); + } + + public void SelectItemsInRect(Rect rect) + { + SelectItemsByPosition(p => rect.Contains(p)); + } + + internal void MapItemClicked(MapItem mapItem, bool controlKey, bool shiftKey) + { + var item = ItemFromMapItem(mapItem); + + if (SelectionMode == SelectionMode.Single) + { + // Single -> set only SelectedItem + + if (SelectedItem != item) + { + SelectedItem = item; + } + else if (controlKey) + { + SelectedItem = null; + } + } + else if (SelectionMode == SelectionMode.Multiple || controlKey) + { + // Multiple or Extended with Ctrl -> toggle item in SelectedItems + + if (SelectedItems.Contains(item)) + { + SelectedItems.Remove(item); + } + else + { + SelectedItems.Add(item); + } + } + else if (shiftKey && SelectedItem != null) + { + // Extended with Shift -> select items in viewport rectangle + + var p1 = MapPanel.GetViewportPosition(MapItemFromItem(SelectedItem)); + var p2 = MapPanel.GetViewportPosition(mapItem); + + if (p1.HasValue && p2.HasValue) + { + SelectItemsInRect(new Rect(p1.Value, p2.Value)); + } + } + else if (SelectedItem != item) + { + // Extended without Control or Shift -> set selected item + + SelectedItem = item; + } } } } diff --git a/MapControl/UWP/MapControl.UWP.csproj b/MapControl/UWP/MapControl.UWP.csproj index e5abf127..46bd689b 100644 --- a/MapControl/UWP/MapControl.UWP.csproj +++ b/MapControl/UWP/MapControl.UWP.csproj @@ -157,6 +157,7 @@ + diff --git a/MapControl/UWP/MapItemsControl.UWP.cs b/MapControl/UWP/MapItemsControl.UWP.cs new file mode 100644 index 00000000..590abe33 --- /dev/null +++ b/MapControl/UWP/MapItemsControl.UWP.cs @@ -0,0 +1,44 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using Windows.System; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Input; + +namespace MapControl +{ + /// + /// Container class for an item in a MapItemsControl. + /// + public class MapItem : ListBoxItem + { + public MapItem() + { + DefaultStyleKey = typeof(MapItem); + + MapPanel.InitMapElement(this); + } + + protected override void OnPointerPressed(PointerRoutedEventArgs e) + { + e.Handled = true; + + (ItemsControl.ItemsControlFromItemContainer(this) as MapItemsControl)?.MapItemClicked( + this, e.KeyModifiers.HasFlag(VirtualKeyModifiers.Control), e.KeyModifiers.HasFlag(VirtualKeyModifiers.Shift)); + } + } + + public partial class MapItemsControl + { + public MapItem MapItemFromItem(object item) + { + return (MapItem)ContainerFromItem(item); + } + + public object ItemFromMapItem(MapItem mapItem) + { + return ItemFromContainer(mapItem); + } + } +} diff --git a/MapControl/WPF/MapControl.WPF.csproj b/MapControl/WPF/MapControl.WPF.csproj index fb0d205a..5b1e1605 100644 --- a/MapControl/WPF/MapControl.WPF.csproj +++ b/MapControl/WPF/MapControl.WPF.csproj @@ -180,6 +180,7 @@ + diff --git a/MapControl/WPF/MapItemsControl.WPF.cs b/MapControl/WPF/MapItemsControl.WPF.cs new file mode 100644 index 00000000..22a47b06 --- /dev/null +++ b/MapControl/WPF/MapItemsControl.WPF.cs @@ -0,0 +1,49 @@ +// XAML Map Control - https://github.com/ClemensFischer/XAML-Map-Control +// © 2018 Clemens Fischer +// Licensed under the Microsoft Public License (Ms-PL) + +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; + +namespace MapControl +{ + /// + /// Container class for an item in a MapItemsControl. + /// + public class MapItem : ListBoxItem + { + public MapItem() + { + DefaultStyleKey = typeof(MapItem); + + MapPanel.InitMapElement(this); + } + + protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) + { + e.Handled = true; + + (ItemsControl.ItemsControlFromItemContainer(this) as MapItemsControl)?.MapItemClicked( + this, Keyboard.Modifiers.HasFlag(ModifierKeys.Control), Keyboard.Modifiers.HasFlag(ModifierKeys.Shift)); + } + } + + public partial class MapItemsControl + { + public MapItem MapItemFromItem(object item) + { + return (MapItem)ItemContainerGenerator.ContainerFromItem(item); + } + + public object ItemFromMapItem(MapItem mapItem) + { + return ItemContainerGenerator.ItemFromContainer(mapItem); + } + + public void SelectItemsInGeometry(Geometry geometry) + { + SelectItemsByPosition(p => geometry.FillContains(p)); + } + } +} diff --git a/MapControl/WPF/Themes/Generic.xaml b/MapControl/WPF/Themes/Generic.xaml index 64af4352..68019ade 100644 --- a/MapControl/WPF/Themes/Generic.xaml +++ b/MapControl/WPF/Themes/Generic.xaml @@ -18,7 +18,7 @@