// WPF MapControl - http://wpfmapcontrol.codeplex.com/ // Copyright © 2012 Clemens Fischer // Licensed under the Microsoft Public License (Ms-PL) using System; using System.Collections; using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; namespace MapControl { /// /// Manages a collection of selectable items on a Map. Uses MapItem as container for items /// and updates the IsCurrent attached property when the Items.CurrentItem property changes. /// public class MapItemsControl : MultiSelector { public static readonly DependencyProperty SelectionModeProperty = DependencyProperty.Register( "SelectionMode", typeof(SelectionMode), typeof(MapItemsControl), new FrameworkPropertyMetadata((o, e) => ((MapItemsControl)o).CanSelectMultipleItems = (SelectionMode)e.NewValue != SelectionMode.Single)); public static readonly DependencyProperty SelectionGeometryProperty = DependencyProperty.Register( "SelectionGeometry", typeof(Geometry), typeof(MapItemsControl), new FrameworkPropertyMetadata((o, e) => ((MapItemsControl)o).SelectionGeometryPropertyChanged((Geometry)e.NewValue))); internal static readonly DependencyPropertyKey IsCurrentPropertyKey = DependencyProperty.RegisterAttachedReadOnly( "IsCurrent", typeof(bool), typeof(MapItemsControl), null); public static readonly DependencyProperty IsCurrentProperty = IsCurrentPropertyKey.DependencyProperty; public MapItemsControl() { Style = (Style)FindResource(typeof(MapItemsControl)); CanSelectMultipleItems = SelectionMode != SelectionMode.Single; Items.CurrentChanging += OnCurrentItemChanging; Items.CurrentChanged += OnCurrentItemChanged; } public SelectionMode SelectionMode { get { return (SelectionMode)GetValue(SelectionModeProperty); } set { SetValue(SelectionModeProperty, value); } } public Geometry SelectionGeometry { get { return (Geometry)GetValue(SelectionGeometryProperty); } set { SetValue(SelectionGeometryProperty, value); } } public static bool GetIsCurrent(UIElement element) { return (bool)element.GetValue(IsCurrentProperty); } public static void SetIsCurrent(UIElement element, bool value) { element.SetValue(IsCurrentPropertyKey, value); } public UIElement GetContainer(object item) { return item != null ? ItemContainerGenerator.ContainerFromItem(item) as UIElement : null; } public object GetItem(DependencyObject container) { return container != null ? ItemContainerGenerator.ItemFromContainer(container) : null; } public IList GetItemsInGeometry(Geometry geometry) { return GetItemsInGeometry(geometry, new ArrayList(Items.Count), Items.Count); } protected override bool IsItemItsOwnContainerOverride(object item) { return item is UIElement; } protected override DependencyObject GetContainerForItemOverride() { return new MapItem(); } protected override void PrepareContainerForItemOverride(DependencyObject element, object item) { base.PrepareContainerForItemOverride(element, item); UIElement container = (UIElement)element; container.MouseLeftButtonDown += ContainerMouseLeftButtonDown; container.TouchDown += ContainerTouchDown; container.TouchUp += ContainerTouchUp; } protected override void ClearContainerForItemOverride(DependencyObject element, object item) { base.ClearContainerForItemOverride(element, item); UIElement container = (UIElement)element; container.MouseLeftButtonDown -= ContainerMouseLeftButtonDown; container.TouchDown -= ContainerTouchDown; container.TouchUp -= ContainerTouchUp; } private void ContainerMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; UIElement container = (UIElement)sender; if (SelectionMode == SelectionMode.Extended && (Keyboard.Modifiers & (ModifierKeys.Control | ModifierKeys.Shift)) == 0) { SelectedItem = GetItem(container); } else { Selector.SetIsSelected(container, !Selector.GetIsSelected(container)); } } private void ContainerTouchDown(object sender, TouchEventArgs e) { e.Handled = true; // get TouchUp event } private void ContainerTouchUp(object sender, TouchEventArgs e) { e.Handled = true; UIElement container = (UIElement)sender; Selector.SetIsSelected(container, !Selector.GetIsSelected(container)); } private void OnCurrentItemChanging(object sender, CurrentChangingEventArgs e) { UIElement container = GetContainer(Items.CurrentItem); if (container != null) { SetIsCurrent(container, false); } } private void OnCurrentItemChanged(object sender, EventArgs e) { UIElement container = GetContainer(Items.CurrentItem); if (container != null) { SetIsCurrent(container, true); } } private void SelectionGeometryPropertyChanged(Geometry geometry) { if (geometry != null) { if (SelectionMode == SelectionMode.Single) { IList items = GetItemsInGeometry(geometry, new ArrayList(1), 1); SelectedItem = items.Count > 0 ? items[0] : null; } else { BeginUpdateSelectedItems(); GetItemsInGeometry(geometry, SelectedItems, Items.Count); EndUpdateSelectedItems(); } } } private IList GetItemsInGeometry(Geometry geometry, IList items, int maxItems) { items.Clear(); if (!geometry.IsEmpty()) { foreach (object item in Items) { UIElement container = GetContainer(item); if (container != null) { ViewportPosition viewportPosition = MapPanel.GetViewportPosition(container); if (viewportPosition != null && geometry.FillContains(viewportPosition.Position)) { items.Add(item); if (items.Count >= maxItems) { break; } } } } } return items; } } }