XAML-Map-Control/MapControl/MapItemsControl.cs

258 lines
8.7 KiB
C#
Raw Normal View History

2012-05-04 12:52:20 +02:00
// WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Collections;
2012-04-25 22:02:53 +02:00
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
2012-04-25 22:02:53 +02:00
using System.Windows.Controls.Primitives;
using System.Windows.Input;
2012-04-25 22:02:53 +02:00
using System.Windows.Media;
namespace MapControl
{
2012-05-04 12:52:20 +02:00
/// <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.
2012-05-04 12:52:20 +02:00
/// </summary>
2012-04-25 22:02:53 +02:00
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));
2012-04-25 22:02:53 +02:00
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;
2012-04-25 22:02:53 +02:00
public MapItemsControl()
{
Style = (Style)FindResource(typeof(MapItemsControl));
CanSelectMultipleItems = SelectionMode != SelectionMode.Single;
2012-04-25 22:02:53 +02:00
Items.CurrentChanging += OnCurrentItemChanging;
Items.CurrentChanged += OnCurrentItemChanged;
}
public Map ParentMap
{
get { return MapPanel.GetParentMap(this); }
}
public SelectionMode SelectionMode
2012-04-25 22:02:53 +02:00
{
get { return (SelectionMode)GetValue(SelectionModeProperty); }
2012-04-25 22:02:53 +02:00
set { SetValue(SelectionModeProperty, value); }
}
public Geometry SelectionGeometry
{
get { return (Geometry)GetValue(SelectionGeometryProperty); }
set { SetValue(SelectionGeometryProperty, value); }
}
public static bool GetIsCurrent(UIElement element)
2012-04-25 22:02:53 +02:00
{
return (bool)element.GetValue(IsCurrentProperty);
2012-04-25 22:02:53 +02:00
}
public static void SetIsCurrent(UIElement element, bool value)
2012-04-25 22:02:53 +02:00
{
element.SetValue(IsCurrentPropertyKey, value);
}
2012-04-25 22:02:53 +02:00
public UIElement GetContainer(object item)
{
return item != null ? ItemContainerGenerator.ContainerFromItem(item) as UIElement : null;
}
2012-04-25 22:02:53 +02:00
public object GetItem(DependencyObject container)
{
return container != null ? ItemContainerGenerator.ItemFromContainer(container) : null;
}
public IList GetItemsInGeometry(Geometry geometry)
{
return GetItemsInGeometry(geometry, new ArrayList());
}
2012-04-25 22:02:53 +02:00
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is UIElement;
2012-04-25 22:02:53 +02:00
}
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;
2012-04-25 22:02:53 +02:00
}
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;
UIElement selectedContainer;
if (SelectionMode != SelectionMode.Extended || (Keyboard.Modifiers & ModifierKeys.Control) != 0)
{
Selector.SetIsSelected(container, !Selector.GetIsSelected(container));
}
else if ((Keyboard.Modifiers & ModifierKeys.Shift) == 0)
{
SelectedItem = GetItem(container);
}
else if ((selectedContainer = GetContainer(SelectedItem)) != null)
{
Point? p1 = MapPanel.GetViewportPosition(selectedContainer);
Point? p2 = MapPanel.GetViewportPosition(container);
if (p1.HasValue && p2.HasValue)
{
Rect rect = new Rect(p1.Value, p2.Value);
BeginUpdateSelectedItems();
SelectedItems.Clear();
SelectedItems.Add(SelectedItem);
foreach (object item in Items)
{
if (item != SelectedItem && IsItemInRect(item, rect))
{
SelectedItems.Add(item);
}
}
EndUpdateSelectedItems();
}
}
2012-04-25 22:02:53 +02:00
}
private void ContainerTouchDown(object sender, TouchEventArgs e)
2012-04-25 22:02:53 +02:00
{
e.Handled = true; // get TouchUp event
}
2012-04-25 22:02:53 +02:00
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)
2012-04-25 22:02:53 +02:00
{
SetIsCurrent(container, false);
2012-04-25 22:02:53 +02:00
}
}
private void OnCurrentItemChanged(object sender, EventArgs e)
2012-04-25 22:02:53 +02:00
{
UIElement container = GetContainer(Items.CurrentItem);
2012-04-25 22:02:53 +02:00
if (container != null)
2012-04-25 22:02:53 +02:00
{
SetIsCurrent(container, true);
2012-04-25 22:02:53 +02:00
}
}
private void SelectionGeometryPropertyChanged(Geometry geometry)
2012-04-25 22:02:53 +02:00
{
if (geometry != null)
{
if (SelectionMode == SelectionMode.Single)
{
SelectedItem = GetFirstItemInGeometry(geometry);
}
else
{
BeginUpdateSelectedItems();
SelectedItems.Clear();
GetItemsInGeometry(geometry, SelectedItems);
EndUpdateSelectedItems();
}
}
}
2012-04-25 22:02:53 +02:00
private object GetFirstItemInGeometry(Geometry geometry)
{
if (!geometry.IsEmpty())
{
foreach (object item in Items)
2012-04-25 22:02:53 +02:00
{
if (IsItemInGeometry(item, geometry))
2012-04-25 22:02:53 +02:00
{
return item;
}
}
}
2012-04-25 22:02:53 +02:00
return null;
}
private IList GetItemsInGeometry(Geometry geometry, IList items)
{
if (!geometry.IsEmpty())
{
foreach (object item in Items)
{
if (IsItemInGeometry(item, geometry))
{
items.Add(item);
2012-04-25 22:02:53 +02:00
}
}
}
return items;
2012-04-25 22:02:53 +02:00
}
private bool IsItemInGeometry(object item, Geometry geometry)
{
UIElement container = GetContainer(item);
Point? viewportPosition;
return container != null
&& (viewportPosition = MapPanel.GetViewportPosition(container)).HasValue
&& geometry.FillContains(viewportPosition.Value);
}
private bool IsItemInRect(object item, Rect rect)
{
UIElement container = GetContainer(item);
Point? viewportPosition;
return container != null
&& (viewportPosition = MapPanel.GetViewportPosition(container)).HasValue
&& rect.Contains(viewportPosition.Value);
}
2012-04-25 22:02:53 +02:00
}
}