private void OnMouseMove(object sender, MouseEventArgs e)
{
if (mouseDown)
{
if (DateTime.UtcNow > lastScrollTime.AddMilliseconds(100))
{
Point currentPointWin = Mouse.GetPosition(scrollViewer);
if (currentPointWin.Y < 16)
{
scrollViewer.LineUp();
scrollViewer.UpdateLayout();
lastScrollTime = DateTime.UtcNow;
}
if (currentPointWin.Y > scrollViewer.ActualHeight - 16)
{
scrollViewer.LineDown();
scrollViewer.UpdateLayout();
lastScrollTime = DateTime.UtcNow;
}
}
Point currentPoint = Mouse.GetPosition(content);
double width = currentPoint.X - startPoint.X + 1;
double height = currentPoint.Y - startPoint.Y + 1;
double left = startPoint.X;
double top = startPoint.Y;
if (isFirstMove)
{
if (Math.Abs(width) <= SystemParameters.MinimumHorizontalDragDistance &&
Math.Abs(height) <= SystemParameters.MinimumVerticalDragDistance)
{
return;
}
isFirstMove = false;
if (!SelectionMultiple.IsControlKeyDown)
{
if (!treeView.ClearSelectionByRectangle())
{
EndAction();
return;
}
}
}
// Debug.WriteLine(string.Format("Drawing: {0};{1};{2};{3}",startPoint.X,startPoint.Y,width,height));
if (width < 1)
{
width = Math.Abs(width - 1) + 1;
left = startPoint.X - width + 1;
}
if (height < 1)
{
height = Math.Abs(height - 1) + 1;
top = startPoint.Y - height + 1;
}
border.Width = width;
Canvas.SetLeft(border, left);
border.Height = height;
Canvas.SetTop(border, top);
border.Visibility = Visibility.Visible;
double right = left + width - 1;
double bottom = top + height - 1;
// Debug.WriteLine(string.Format("left:{1};right:{2};top:{3};bottom:{4}", null, left, right, top, bottom));
SelectionMultiple selection = (SelectionMultiple)treeView.Selection;
bool foundFocusItem = false;
foreach (var item in items)
{
FrameworkElement itemContent = (FrameworkElement)item.Template.FindName("PART_Header", item);
if (itemContent == null)
{
continue;
}
Point p = ((FrameworkElement)itemContent.Parent).TransformToAncestor(content).Transform(new Point());
double itemLeft = p.X;
double itemRight = p.X + itemContent.ActualWidth - 1;
double itemTop = p.Y;
double itemBottom = p.Y + itemContent.ActualHeight - 1;
// Debug.WriteLine(string.Format("element:{0};itemleft:{1};itemright:{2};itemtop:{3};itembottom:{4}",item.DataContext,itemLeft,itemRight,itemTop,itemBottom));
// Compute the current input states for determining the new selection state of the item
bool intersect = !(itemLeft > right || itemRight <left || itemTop> bottom || itemBottom < top);
bool initialSelected = initialSelection != null && initialSelection.Contains(item.DataContext);
bool ctrl = SelectionMultiple.IsControlKeyDown;
// Decision matrix:
// If the Ctrl key is pressed, each intersected item will be toggled from its initial selection.
// Without the Ctrl key, each intersected item is selected, others are deselected.
//
// newSelected
// ─────────┬───────────────────────
// │ intersect
// │ 0 │ 1
// ├───────────┴───────────
// │ initial
// │ 0 │ 1 │ 0 │ 1
// ─────────┼─────┼─────┼─────┼─────
// ctrl 0 │ 0 │ 0 │ 1 │ 1 = intersect
// ─────────┼─────┼─────┼─────┼─────
// 1 │ 0 │ 1 │ 1 │ 0 = intersect XOR initial
//
bool newSelected = intersect ^ (initialSelected && ctrl);
// The new selection state for this item has been determined. Apply it.
if (newSelected)
{
// The item shall be selected
if (!treeView.SelectedItems.Contains(item.DataContext))
{
// The item is not currently selected. Try to select it.
if (!selection.SelectByRectangle(item))
{
if (selection.LastCancelAll)
{
EndAction();
return;
}
}
}
}
else
{
// The item shall be deselected
if (treeView.SelectedItems.Contains(item.DataContext))
{
// The item is currently selected. Try to deselect it.
if (!selection.DeselectByRectangle(item))
{
if (selection.LastCancelAll)
{
EndAction();
return;
}
}
}
}
// Always focus and bring into view the item under the mouse cursor
if (!foundFocusItem &&
currentPoint.X >= itemLeft && currentPoint.X <= itemRight &&
currentPoint.Y >= itemTop && currentPoint.Y <= itemBottom)
{
FocusHelper.Focus(item, true);
scrollViewer.UpdateLayout();
foundFocusItem = true;
}
}
if (e != null)
{
e.Handled = true;
}
}
}