Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Реализация Drag and Drop на языке C# в Visual Studio

Anna | 17.06.2014 | нет комментариев

Введение

Добросердечного времени суток, уважаемые прогрчане. Данный пост не будет особенно отличать оригинальностью, уникальностью либо гениальностью. Я бы назвал его начальство по пользованию. Думаю многие бывалые программисты сделают уйма примечаний, за что я в целом буду только признателен, тем больше если это будет конструктивная критика. Но, в целом, мой пост ориентирован огромнее на начинающих программистов, так как бывалые скорее каждого сталкивались с такой задачей и теснее решили её сами.

Выходит, о чем же будет сегодняшний наш разговор. Как вы осознали из наименования, я расскажу как реализовать Drag and Drop на языке C# в Visual Studio. Думаю многие начинающие программисты сталкивались с такой задачей, когда существует несколько списков и вы хотите перетащить элементы из одного в иной, но придумать как это сделать либо обнаружить внятный мануал не могли. И чай так хочется, чтоб в вашем приложении было все прекрасно и современно, а доводилось обходится простым выбором элемента и переносом его в иной по нажатию на кнопку. Верю сегодня этим простым начальством я сумею всё-таки подмогнуть парочек юных воинов(я и сам такой, как мне кажется) и развеять всякие задачи связанные с реализацией данного функционала.

Хочу подметить, что я не буду детально рассматривать как обнаружить либо добавить тот либо иной элемент на форму, не буду также детально описывать свойства объектов.

С чего все начиналось

Лаконично расскажу с чего все начиналось и что мы с вами обязаны будем сделать(ТЗ). Началось всё с того, что моей задачей стала реализация автомата с напитками, причём полная реализация, с учетом всех нюансов, таких как замена напитков, их цен, пополнение кассы автомата без применение кода и многое другое, что могло быть опущено при других обстоятельствах. Но я подумал, если делать, то максимально реалистичнои решил добавить drag and drop денег из кошелька в слот для денег с чем пришлось довольно помучатся, но что придало моей программе изюминку.

Техническое задание

У нас имеется два объекта: ListView, тот, что представляет наш кошелёк и ListBox, в котором при перетаскивании будет возникать наименование купюры либо монеты. Нужно сделать программу, которая дозволит перетаскивать элементы из объекта ListView в ListBox без дополнительных кнопок.

Ну, что ж, вызов принят. Приступим.

Шаг 1 Создание рабочей области

Создаем новейший план Windows Form Applicarion и добавляем на форму следующие элементы:

  1. ListView. Наш кошелёк откуда мы будем перетаскивать денежку. Напомню, что все элементы будут представлены в виде изображений монет и купюр.
  2. ListBox. Список, куда мы будем всё это перетаскивать, в котором будут отображаться наименования номиналов.
  3. ImageList. Именно отсель мы получим наши изображения денег.
  4. Label. Вспомогательный элемент, тот, что будет показывать в какую позицию будет добавлено наименование в ListBox.

Шаг 2 Подготовка элементов

Добавляем в ImageList картинки отсель. Называем их так, чтоб вам потом было ясно, где какая картинка. Позднее осознаете для чего. В свойствах ListView есть поле View, я предпочел режим просмотра Large icon, но вы можете предпочесть Small icon. В зависимости от выбора в поле LargeImageList либо SmallImageList выбираете имя вашего объекта ImageList. Но это еще не всё. Сейчас открываем качество Items для всё того же ListView и добавляем новейший элемент. Для него в поле значение ImageIndex изображение, а в поле Tag прописываем текст, согласно номиналу на изображении. И так добавляем все нужные нам элементы.
Сейчас все картинки отображаются в ListView и имеют «наименование»(Tag). Настраиваем по размерам все объекты и балуемся настройками внешнего вида на свой вкус. Советую всякий элемент называть так, чтоб было ясно для чего он.
Вот что получилось у меня:
image

Шаг 3 Код

Пришло время самой главной и самой трудной части. В целом, скопировать и вставить будет не трудно, но значимо осознать код! Выжпрограммисты;)
Примечание. Комментарии у меня на английском по двум причинам. Создавалось все для иностранного человека, посему комментарии на английском и переводить мне лень. А вторая повод — я неизменно пишу комментарии на английском, чтоб неизменно дозволено было код показать «за бугор» и не париться с переводом комментариев.

Добавляем события для объектов.
Для ListView:

  1. MouseDown
  2. MouseUp
  3. MouseMove

Для ListBox:

  1. DragOver
  2. DragDrop
  3. DragEnter
  4. DragLeave

Сейчас всё готов для написания кода. Включаем наблюдательность, отключаем мобильные телефоны и другие отвлекающие факторы(кота тоже дозволено отключить).
В первую очередь добавим в предисловие класса переменные, которые нам сгодятся в последующем. Описывать их не буду, так как их призвание вы осознаете в коде.

        private int indexOfItemUnderMouseToDrag;
        private int indexOfItemUnderMouseToDrop;        

        private Rectangle dragBoxFromMouseDown;
        private Point screenOffset;
ListView MouseDown

Это событие будем протекать в тот момент, когда вы нажмете на левую кнопку мыши в объекте ListView.

       private void ListDragSource_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) 
        {
            // Get the index of the item the mouse is below.
            indexOfItemUnderMouseToDrag = ListDragSource.Items.IndexOf( ListDragSource.GetItemAt(e.X, e.Y) );

            if (indexOfItemUnderMouseToDrag != ListBox.NoMatches) 
            {

                // Remember the point where the mouse down occurred. The DragSize indicates
                // the size that the mouse can move before a drag event should be started.                
                Size dragSize = SystemInformation.DragSize;

                // Create a rectangle using the DragSize, with the mouse position being
                // at the center of the rectangle.
                dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width /2),
                                                               e.Y - (dragSize.Height /2)), dragSize);
            } 
            else
                // Reset the rectangle if the mouse is not over an item in the ListBox.
                dragBoxFromMouseDown = Rectangle.Empty;
        }
ListView MouseUp

Отпустив кнопку мышь мы механически «бросаем» объект.

            private void ListDragSource_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) {
            // Reset the drag rectangle when the mouse button is raised.
            dragBoxFromMouseDown = Rectangle.Empty;
        }
ListView MouseMove

Двигая мышку мы вызываем это событие, причём трудиться оно начинает только если мы вышли за пределы нашего «кошелька».
Хочу обратить ваше внимание на строку:

 ListDragSource.Items.RemoveAt(indexOfItemUnderMouseToDrag);   

Ее дозволено так же запрограммировать не только на удаление, но и на уменьшение числа таких элементов в списке, если их несколько. В данном случае всё зависит от цели и вашей фантазии. Выбор действия(перемещение либо копирование) описан в части DragOver.

        private void ListDragSource_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
            {
                // If the mouse moves outside the rectangle, start the drag.
                if (dragBoxFromMouseDown != Rectangle.Empty &&
                    !dragBoxFromMouseDown.Contains(e.X, e.Y))
                {
                    // The screenOffset is used to account for any desktop bands 
                    // that may be at the top or left side of the screen when 
                    // determining when to cancel the drag drop operation.
                    screenOffset = SystemInformation.WorkingArea.Location;

                    // Proceed with the drag-and-drop, passing in the list item.                    
                    DragDropEffects dropEffect = ListDragSource.DoDragDrop(ListDragSource.Items[indexOfItemUnderMouseToDrag], 
                        DragDropEffects.All);

                    // If the drag operation was a move then remove the item.
                    if (dropEffect == DragDropEffects.Move)
                    {
                        //You also can delete item or decrese it, or you can do nothing
                        ListDragSource.Items.RemoveAt(indexOfItemUnderMouseToDrag);    

                        // Selects the previous item in the list as long as the list has an item.
                        if (indexOfItemUnderMouseToDrag > 0)
                            ListDragSource.Items[indexOfItemUnderMouseToDrag - 1].Selected = true;

                        else if (ListDragSource.Items.Count > 0)
                            // Selects the first item.
                            ListDragSource.Items[0].Selected = true;
                    }
                }
            }
        }
ListBox DragOver

В зависимости от задачи нам могут потребуется различные действия с нашими элементами из списка. Перемещение, копирование — всё это может сгодится. В коде ниже реализовано следующее:

  • По умолчанию все элементы будут перемещаться
  • При зажатом Ctrl все элементы будут копироваться
 private void ListDragTarget_DragOver(object sender, System.Windows.Forms.DragEventArgs e) 
        {
            if ((e.KeyState & 8) == 8 && 
                (e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy) 
            {
                 //CTL KeyState for copy.
                e.Effect = DragDropEffects.Copy;
            } 
            else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)  
            {
                // By default, the drop action should be move, if allowed.
                e.Effect = DragDropEffects.Move;
            } 
            else
                e.Effect = DragDropEffects.None;

             //Get the index of the item the mouse is below. 
             //The mouse locations are relative to the screen, so they must be 
             //converted to client coordinates.
            indexOfItemUnderMouseToDrop = 
                ListDragTarget.IndexFromPoint(ListDragTarget.PointToClient(new Point(e.X, e.Y)));

            // Updates the label text.
            if (indexOfItemUnderMouseToDrop != ListBox.NoMatches)
                DropLbl.Text = "Drops before item #"   (indexOfItemUnderMouseToDrop   1);
            else
                DropLbl.Text = "Drops at the end.";

        }
ListBox DragDrop

Добавление перетаскиваемого объекта в новейший список. Тут самое главное это довод sender, тот, что является нашим перетаскиваемым элементом. И тут вновь включается ваша фантазия. В данном случае, я легко получаю значение Tag из полученного объекта(помните мы добавляли в поле Tag наименования номиналов?). Верно таким же образом вы можете реализовать всё, что пожелает ваша душа.

private void ListDragTarget_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
        {
            // Ensure that the list item index is contained in the data.
            Object item = (object)e.Data.GetData(typeof(System.Windows.Forms.ListViewItem));

            // Perform drag-and-drop, depending upon the effect.
            if (e.Effect == DragDropEffects.Copy ||
                e.Effect == DragDropEffects.Move)
            {

                // Insert the item at the specified index or at the end
                if (indexOfItemUnderMouseToDrop != ListBox.NoMatches)
                    ListDragTarget.Items.Insert(indexOfItemUnderMouseToDrop, ((ListViewItem)item).Tag.ToString());
                else
                    ListDragTarget.Items.Add(((ListViewItem)item).Tag.ToString());

            }
            // Reset the label text.
            DropLbl.Text = "None";
        }
ListBox DragEnter,DragLeave

Наконец, самое последнее, это «сброс» нашего Label. Так как если этого не сделать, то он продолжить нам показывать в какое место списка будет добавлен файл, даже если файл теснее добавлен.

        private void ListDragTarget_DragEnter(object sender, System.Windows.Forms.DragEventArgs e) {
            // Reset the label text.
            DropLbl.Text = "None";
        }

        private void ListDragTarget_DragLeave(object sender, System.EventArgs e) {
            // Reset the label text.
            DropLbl.Text = "None";
        }

Завершение

Остается только запустить приложение и убедиться, что всё работает(не позабудьте протестировать программу с зажатым Ctrl). Сейчас, сделав всё написанное выше, вы сумеете адаптировать данный код под свои цели. Добавить счетчики для подсчета объектов, перетаскивать объекты не только из списков в списки, но и многое другое сейчас дозволено реализовать в кратчайшие сроки.

Задание на дом

1. Добавьте контроль числа монет в ListView(с поддержкой счетчика либо любым иным комфортным методом). Реализуйте не удаление монеты из ListView, а уменьшение их числа.
2. Добавьте всякий новейший объект(какой именно вы обязаны определить сами) и перетащите в него изображение из ListView. Всякое новое перетаскивание должно удалять предыдущее изображение.
Примечание: Дозволено добавить сразу ListView и добавлять в него фото в виде новых элементов. Не позабудьте учесть, что если монетка(купюра) были добавлены ранее, то нужно не добавлять новейший элемент, а увеличить число ветхих элементов.

На этом я заканчиваю свое начальство, верю, что оно кому-то будет пригодным. Спасибо за внимание!

Источник: programmingmaster.ru
Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB