punker76 / gong-wpf-dragdrop

The GongSolutions.WPF.DragDrop library is a drag'n'drop framework for WPF
BSD 3-Clause "New" or "Revised" License
2.29k stars 401 forks source link

DragDrop initiated by Messagebox #83

Closed hemets closed 10 years ago

hemets commented 10 years ago

i have a strange problem with drag&drop in listview, when i have to show a messagebox on item selection.

this can happen, when the currently selected item has unsaved properties and the user selects a new listitem without saving the changes of openend one.

after the messagebox has been closed by user interaction, drag&drop moves the new clicked item in list nearby the mouse position in window .. without a started drag&drop action.

i have no idea how to handle that, or if i do something wrong

Here a simplified example to simulate the problem:

The xaml

<Window x:Class="Admin_TestApp.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
        Title="Window1"
        Height="300"
        Width="555">
    <Grid>
        <ListView dd:DragDrop.IsDragSource="True"
                  dd:DragDrop.IsDropTarget="True"
                  SelectionMode="Single"
                  ItemsSource="{Binding MyCollection}"
                  SelectedItem="{Binding MySelectedItem}">
        </ListView>
    </Grid>
</Window>

The code behind

using Admin_TestApp.ViewModel;
using GalaSoft.MvvmLight.Messaging;
using System.Windows;

namespace Admin_TestApp
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();

            DataContext = new TestListViewModel();

            Messenger.Reset();
            Messenger.Default.Register<DialogMessage>(this, msg =>
            {
                MessageBoxResult result = MessageBox.Show(msg.Content, msg.Caption, msg.Button, msg.Icon);
                msg.ProcessCallback(result);
            });
        }
    }
}

And the viewmodel

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Messaging;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;

namespace Admin_TestApp.ViewModel
{
    internal class TestListViewModel : ViewModelBase
    {
        public ObservableCollection<string> MyCollection { get; set; }

        public TestListViewModel()
        {
            MyCollection = new ObservableCollection<string>(new List<string>(){
                "List Entry No. 1",
                "List Entry No. 2",
                "List Entry No. 3",
                "List Entry No. 4",
                "List Entry No. 5",
                "List Entry No. 6",
                "List Entry No. 7"
            });
        }

        private string _selectedItem;

        public string MySelectedItem
        {
            get { return _selectedItem; }
            set
            {
                var message = new DialogMessage("Something is happened!",
                    DialogMessageCallbackHandler)
                {
                    Caption = "Something is happened",
                    Button = MessageBoxButton.OK,
                    Icon = MessageBoxImage.Question
                };

                Messenger.Default.Send(message);

                _selectedItem = value;
                RaisePropertyChanged(() => MySelectedItem);
            }
        }

        private void DialogMessageCallbackHandler(MessageBoxResult result)
        {
            // do something
        }
    }
}

you can download the full sample project to simulate the problem here: https://www.dropbox.com/s/nmtteuib4os91xf/Admin_TestApp.zip

gpeter commented 10 years ago

I ran into this issue as well. Apparently the dialog causes the control to never get the notification that the mouse was released. I resolved it (I think) by inserting 5 lines of code in DragDrop.DragSourcePreviewMouseMove as follows:

    private static void DragSource_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (m_DragInfo != null && !m_DragInProgress)
        {
            if (e.LeftButton == MouseButtonState.Released)       // start insertion
            {
                m_DragInfo = null;
                return;
            }                                           // end insertion

            var dragStart = m_DragInfo.DragStartPosition;

This makes sure the mouse is still down before starting a drag.

hemets commented 10 years ago

Thank you very much, i will try this as soon as possible!

geetings, andi