同一页面上的两个重新排序列表框,防止用户之间的拖放

时间:2015-08-07 18:40:46

标签: c# wpf listbox

我有一个WPF c#应用程序,它有一个窗口,两个重新排序列表框紧挨着。我使用this link中的示例来使列表框用户控制。不幸的是,这允许用户从一个盒子拖动而在另一个盒子中拖放。我怎样才能确保这不会发生?

这是我的代码:

    public void setItems(List<string> values){
        _items = new ObservableCollection<Item>();
        foreach (string s in values)
        {
            _items.Add(new Item(s));
        }

        listBox.DisplayMemberPath = "Name";
        listBox.ItemsSource = _items;

        listBox.PreviewMouseMove += ListBox_PreviewMouseMove;

        var style = new Style(typeof(ListBoxItem));
        style.Setters.Add(new Setter(ListBoxItem.AllowDropProperty, true));
        style.Setters.Add(
            new EventSetter(
                ListBoxItem.PreviewMouseLeftButtonDownEvent,
                new MouseButtonEventHandler(ListBoxItem_PreviewMouseLeftButtonDown)));
        style.Setters.Add(
                new EventSetter(
                    ListBoxItem.DropEvent,
                    new DragEventHandler(ListBoxItem_Drop)));
        listBox.ItemContainerStyle = style;
    }


    private void ListBox_PreviewMouseMove(object sender, MouseEventArgs e)
    {

            Point point = e.GetPosition(null);
            Vector diff = _dragStartPoint - point;
            if (e.LeftButton == MouseButtonState.Pressed &&
                (Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance ||
                    Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance))
            {
                var lb = sender as ListBox;
                var lbi = FindVisualParent<ListBoxItem>(((DependencyObject)e.OriginalSource));
                if (lbi != null)
                {
                    DragDrop.DoDragDrop(lbi, lbi.DataContext, DragDropEffects.Move);
                }
            }

    }


    private void ListBoxItem_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _dragStartPoint = e.GetPosition(null);
    }


    private void ListBoxItem_Drop(object sender, DragEventArgs e)
    {
        if (sender is ListBoxItem)
        {
            var source = e.Data.GetData(typeof(Item)) as Item;
            var target = ((ListBoxItem)(sender)).DataContext as Item;


                int sourceIndex = listBox.Items.IndexOf(source);
                int targetIndex = listBox.Items.IndexOf(target);

                Debug.WriteLine("Target: " + targetIndex.ToString());

                Move(source, sourceIndex, targetIndex);

        }
    }


    private void Move(Item source, int sourceIndex, int targetIndex)
    {
        if (sourceIndex < targetIndex)
        {
            _items.Insert(targetIndex + 1, source);
            _items.RemoveAt(sourceIndex);
        }
        else
        {
            int removeIndex = sourceIndex + 1;
            if (_items.Count + 1 > removeIndex)
            {
                _items.Insert(targetIndex, source);
                _items.RemoveAt(removeIndex);
            }
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我想出来以防其他人有类似的问题...

我将Move功能更改为以下内容:

 private void Move(Item source, int sourceIndex, int targetIndex)
        {
            IList<Item> prevItems = _items;

            try
            {
                _items.RemoveAt(sourceIndex);
                _items.Insert(targetIndex, source);

            }
            catch(ArgumentOutOfRangeException)
            {
                //User doesn't need to be notified about this. It just means that they dragged out of the box they were ordering. 
                //The application does not need to be stopped when this happens.
                _items = prevItems;
                Debug.WriteLine("User tried to drag between boxes.. Order of boxes were not changed. ");

            }
        }

我意识到如果我首先删除该项目,那么我将不必担心根据sourceIndex相对于targetIndex的位置更改目标或删除索引。相反,我可以将它包装在try catch中并查找ArgumentOutOfRangeException,如果用户尝试拖放之间将发生这种情况。如果发生这种情况,我将该框重置为之前的项目。

据我所知,这个解决方案运行正常......可能有一个更简单的方法可以解决这个问题。