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

本文关键字:列表 排序 拖放 之间 用户 一页 两个 新排序 | 更新日期: 2023-09-27 18:06:50

我有一个WPF c#应用程序,它有一个窗口,两个重新排序列表框紧挨着彼此。我使用这个链接中的示例来创建列表框用户控件。不幸的是,这允许用户从一个框中拖动并放入另一个框。我怎样才能确保这不会发生?

下面是我的代码:
    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);
            }
        }
    }
}

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

我弄清楚了,以防其他人有类似的问题…

我将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,如果用户试图在两者之间拖放,就会发生这种情况。如果发生这种情况,我将重置为之前的项目。

据我所知,这个解决方案很好…也许有一种更简单的方法来解决这个问题。