XAML-Map-Control/MapControl/MapItemsControl.cs

207 lines
7.2 KiB
C#

// 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
{
/// <summary>
/// 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.
/// </summary>
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;
}
}
}