Ejemplo n.º 1
0
        // If the types of the dragged data and ItemsControl's source are compatible,
        // there are 3 situations to have into account when deciding the drop target:
        // 1. mouse is over an items container
        // 2. mouse is over the empty part of an ItemsControl, but ItemsControl is not empty
        // 3. mouse is over an empty ItemsControl.
        // The goal of this method is to decide on the values of the following properties:
        // targetItemContainer, insertionIndex and isInFirstHalf.
        private void DecideDropTarget(DragEventArgs e, object draggedItem)
        {
            _isInFirstHalf        = false;
            _targetItemContainer  = null;
            _targetOrientation    = Orientation.Vertical;
            _targetInsertionIndex = -1;
            if (!IsDropDataAllowed(draggedItem))
            {
                // Mismatched type
                e.Effects = DragDropEffects.None;
                return;
            }
            var targetItemsControlCount = _targetItemsControl.Items.Count;

            if (targetItemsControlCount == 0)
            {
                // Over an empty items control, insert at the beginning
                _targetInsertionIndex = 0;
                return;
            }
            // Find the items panel
            _targetOrientation = DragDropUtilities.GetOrientation(
                _targetItemsControl.ItemContainerGenerator.ContainerFromIndex(0),
                GetDefaultOrientation(_targetItemsControl));
            // This is the element we are pointing to (as long as it has a background)
            _targetItemContainer = _targetItemsControl.ContainerFromElement((DependencyObject)e.OriginalSource) as FrameworkElement;
            if (_targetItemContainer != null)
            {
                var positionRelativeToItemContainer = e.GetPosition(_targetItemContainer);
                _isInFirstHalf        = DragDropUtilities.IsInFirstHalf(_targetItemContainer, positionRelativeToItemContainer, _targetOrientation);
                _targetInsertionIndex = _targetItemsControl.ItemContainerGenerator.IndexFromContainer(_targetItemContainer);
                if (!_isInFirstHalf)
                {
                    // Insert after the target if more than half way through
                    _targetInsertionIndex++;
                }
                return;
            }
            // Fallback to the last item in the container (always show at bottom)
            _targetItemContainer  = _targetItemsControl.ItemContainerGenerator.ContainerFromIndex(targetItemsControlCount - 1) as FrameworkElement;
            _targetInsertionIndex = targetItemsControlCount;
        }
Ejemplo n.º 2
0
        private void DropTarget_Drop(object sender, DragEventArgs e)
        {
            e.Handled = true;
            var draggedItem = e.Data.GetData(_format.Name);

            if (draggedItem == null)
            {
                return;
            }
            var indexRemoved = -1;

            if ((e.Effects & DragDropEffects.Move) != 0)
            {
                indexRemoved = DragDropUtilities.RemoveItemFromItemsControl(_sourceItemsControl, draggedItem);
            }
            // This happens when we drag an item to a later position within the same ItemsControl.
            if (indexRemoved != -1 && _sourceItemsControl == _targetItemsControl && indexRemoved < _targetInsertionIndex)
            {
                _targetInsertionIndex--;
            }
            DragDropUtilities.InsertItemIntoItemsControl(_targetItemsControl, draggedItem, _targetInsertionIndex);
            RemoveDraggedAdorner();
            RemoveInsertionAdorner();
        }
Ejemplo n.º 3
0
        // Drag = mouse down + move by a certain amount
        private void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
        {
            if (_draggedData == null)
            {
                return;
            }
            // Only drag when user moved the mouse by a reasonable amount.
            if (!DragDropUtilities.IsMovementBigEnough(_initialMousePosition, e.GetPosition(_sourceItemsControl)))
            {
                return;
            }
            // Definately was our event
            e.Handled = true;
            // Get the data ready to be dropped
            var data = new DataObject(_format.Name, _draggedData);

            // From now on, get the data from the DataObject
            _draggedData = null;

            // Adding events to the parent to make sure the dragged adorner comes up when mouse is not over a drop target
            var parent = GetDragParent(_sourceItemsControl);
            DependencyProperty backgroundProperty = null;
            bool setBackground     = false;
            bool previousAllowDrop = false;

            if (parent != null)
            {
                backgroundProperty = DragDropUtilities.GetDependencyPropertyByName(parent.GetType(), "BackgroundProperty");
                // If the parent does not draw a background (like a grid by default) then you will not get drag events
                // Unfortunately Background is defined in several classes e.g. Control, Panel not a single base class
                // so use reflection to get and set the current value
                if (backgroundProperty != null)
                {
                    var background = parent.GetValue(backgroundProperty) as Brush;
                    if (background == null)
                    {
                        parent.SetValue(backgroundProperty, Brushes.Transparent);
                        setBackground = true;
                    }
                    previousAllowDrop = parent.AllowDrop;
                    parent.AllowDrop  = true;
                    parent.DragEnter += Parent_DragEnter;
                    parent.DragOver  += Parent_DragOver;
                    parent.DragLeave += Parent_DragLeave;
                }
            }


            var effects = DragDrop.DoDragDrop((DependencyObject)sender, data, DragDropEffects.Move);

            // Without this call, there would be a bug in the following scenario: Click on a data item, and drag
            // the mouse very fast outside of the window. When doing this really fast, for some reason I don't get
            // the Window leave event, and the dragged adorner is left behind.
            // With this call, the dragged adorner will disappear when we release the mouse outside of the window,
            // which is when the DoDragDrop synchronous method returns.
            RemoveDraggedAdorner();

            if (parent != null)
            {
                if (backgroundProperty != null)
                {
                    if (setBackground)
                    {
                        parent.ClearValue(backgroundProperty);
                        setBackground = false;
                    }
                    parent.AllowDrop  = previousAllowDrop;
                    parent.DragEnter -= Parent_DragEnter;
                    parent.DragOver  -= Parent_DragOver;
                    parent.DragLeave -= Parent_DragLeave;
                }
            }
        }