/// <summary>
        /// Is called when a drag-and-drop operation is completed in order to raise the Dropped event.
        /// </summary>
        /// <param name="e">Event arguments which hold information on the completed operation.</param>
        /// <remarks>Is called for the target as well as for the source.
        /// The role a control plays (source or target) can be determined from e.Operation.</remarks>
        public virtual void OnDropped(DroppedEventArgs e)
        {
            var dropEvent = Dropped;

            if (dropEvent != null)
            {
                dropEvent(this, e);
            }
        }
        protected override void OnDragDrop(DragEventArgs drgevent)
        {
            base.OnDragDrop(drgevent);

            _visualCue.Clear();

            // Retrieve the drag item data.
            // Conditions have been testet in OnDragEnter and OnDragOver, so everything should be ok here.
            IDragDropSource src = drgevent.Data.GetData("IDragDropSource") as IDragDropSource;

            object[] srcItems = src.GetSelectedItems();

            // If the list box is sorted, we don't know where the items will be inserted
            // and we will have troubles selecting the inserted items. So let's disable sorting here.
            bool sortedSave = Sorted;

            Sorted = false;

            // Insert at the currently hovered row.
            int row         = DropIndex(drgevent.Y);
            int insertPoint = row;

            if (row >= Items.Count)
            { // Append items to the end.
                Items.AddRange(srcItems);
            }
            else
            { // Insert items before row.
                foreach (object item in srcItems)
                {
                    Items.Insert(row++, item);
                }
            }
            // Remove all the selected items from the source, if moving.
            DropOperation operation; // Remembers the operation for the event we'll raise.

            if (drgevent.Effect == DragDropEffects.Move)
            {
                int adjustedInsertPoint = insertPoint;
                src.RemoveSelectedItems(ref adjustedInsertPoint);
                if (src == this)
                { // Items are being reordered.
                    insertPoint = adjustedInsertPoint;
                    operation   = DropOperation.Reorder;
                }
                else
                {
                    operation = DropOperation.MoveToHere;
                }
            }
            else
            {
                operation = DropOperation.CopyToHere;
            }

            // Adjust the selected items in the target.
            ClearSelected();
            if (SelectionMode == SelectionMode.One)
            { // Select the first item inserted.
                SelectedIndex = insertPoint;
            }
            else if (SelectionMode != SelectionMode.None)
            { // Select the inserted items.
                for (int i = insertPoint; i < insertPoint + srcItems.Length; i++)
                {
                    SetSelected(i, true);
                }
            }

            // Now that we've selected the inserted items, restore the "Sorted" property.
            Sorted = sortedSave;

            // Notify the target (this control).
            DroppedEventArgs e = new DroppedEventArgs
            {
                Operation    = operation,
                Source       = src,
                Target       = this,
                DroppedItems = srcItems
            };

            OnDropped(e);

            // Notify the source (the other control).
            if (operation != DropOperation.Reorder)
            {
                e = new DroppedEventArgs
                {
                    Operation    = operation == DropOperation.MoveToHere ? DropOperation.MoveFromHere : DropOperation.CopyFromHere,
                    Source       = src,
                    Target       = this,
                    DroppedItems = srcItems
                };
                src.OnDropped(e);
            }

            ClearSelected();
        }