c# - 使用 MVVM 通过拖放重新排序 ItemsControl

标签 c# wpf mvvm drag-and-drop itemscontrol

我最近问了一个关于如何使用拖放重新排序 ItemsControl 的问题 (ItemsControl Drag and Drop)。答案暂时很好(下面的代码),但现在我正在尝试实现 MVVM,并且当前的解决方案需要访问 View 中的项目。任何想法如何改变它以与 MVVM 一起工作?我计划使附加属性绑定(bind)到命令,但我不知道如何摆脱诸如以下行:int index = (int)(e.GetPosition(DimsContainer).X/width);

当前拖放代码:

private void DimsContainer_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _isDown = true;
        _startPoint = e.GetPosition(this.DimsContainer);
    }

    private void DimsContainer_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        _isDown = false;
        _isDragging = false;

        if (_realDragSource != null)
        {
            _realDragSource.ReleaseMouseCapture();
        }
    }

    private void DimsContainer_PreviewMouseMove(object sender, MouseEventArgs e)
    {
        if (_isDown)
        {
            if ((_isDragging == false) &&
                ((Math.Abs(e.GetPosition(this.DimsContainer).X - _startPoint.X) >
                    SystemParameters.MinimumHorizontalDragDistance) ||
                 (Math.Abs(e.GetPosition(this.DimsContainer).Y - _startPoint.Y) >
                    SystemParameters.MinimumVerticalDragDistance)))
            {
                _isDragging = true;
                _realDragSource = e.Source as UIElement;
                _realDragSource.CaptureMouse();

                double width = ((FrameworkElement)(this.DimsContainer.ItemContainerGenerator.ContainerFromIndex(0))).ActualWidth;
                int index = (int)(e.GetPosition(DimsContainer).X / width);
                DragDrop.DoDragDrop(_realDragSource, new DataObject("UIElement", index, true), DragDropEffects.Move);
            }
        }
    }

    private void DimsContainer_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("UIElement"))
        {
            e.Effects = DragDropEffects.Move;
        }
    }

    private void DimsContainer_Drop(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent("UIElement"))
        {
            int sourceIndex = (int)e.Data.GetData("UIElement");
            int removedObject = this.indices[sourceIndex];
            this.indices.RemoveAt(sourceIndex);

            UIElement droptarget = e.Source as UIElement;

            // If a drag/drop is happening, there is definitely
            // one child in the DimsContainer
            double width = ((FrameworkElement)(this.DimsContainer.ItemContainerGenerator.ContainerFromIndex(0))).ActualWidth;
            int index = (int)(e.GetPosition(DimsContainer).X / width);

            try
            {
                this.indices.Insert(index, removedObject);
            }
            catch (InvalidOperationException)
            {
                // ignore
            }

            _isDown = false;
            _isDragging = false;
            _realDragSource.ReleaseMouseCapture();
        }
    }

    public static int RemoveItemFromItemsControl(ItemsControl itemsControl, object itemToRemove)
    {
        int indexToBeRemoved = -1;
        if (itemToRemove != null)
        {
            indexToBeRemoved = itemsControl.Items.IndexOf(itemToRemove);

            if (indexToBeRemoved != -1)
            {
                IEnumerable itemsSource = itemsControl.ItemsSource;
                if (itemsSource == null)
                {
                    itemsControl.Items.RemoveAt(indexToBeRemoved);
                }
                // Is the ItemsSource IList or IList<T>? If so, remove the item from the list.
                else if (itemsSource is IList)
                {
                    ((IList)itemsSource).RemoveAt(indexToBeRemoved);
                }
                else
                {
                    Type type = itemsSource.GetType();
                    Type genericIListType = type.GetInterface("IList`1");
                    if (genericIListType != null)
                    {
                        type.GetMethod("RemoveAt").Invoke(itemsSource, new object[] { indexToBeRemoved });
                    }
                }
            }
        }
        return indexToBeRemoved;
    }

    public static void InsertItemInItemsControl(ItemsControl itemsControl, object itemToInsert, int insertionIndex)
    {
        if (itemToInsert != null)
        {
            IEnumerable itemsSource = itemsControl.ItemsSource;

            if (itemsSource == null)
            {
                itemsControl.Items.Insert(insertionIndex, itemToInsert);
            }
            // Is the ItemsSource IList or IList<T>? If so, insert the dragged item in the list.
            else if (itemsSource is IList)
            {
                ((IList)itemsSource).Insert(insertionIndex, itemToInsert);
            }
            else
            {
                Type type = itemsSource.GetType();
                Type genericIListType = type.GetInterface("IList`1");
                if (genericIListType != null)
                {
                    type.GetMethod("Insert").Invoke(itemsSource, new object[] { insertionIndex, itemToInsert });
                }
            }
        }
    }

最佳答案

关于c# - 使用 MVVM 通过拖放重新排序 ItemsControl,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6507553/

相关文章:

wpf - WPF 中不存在另一个名称的问题

c# - 无法使用 jquery ajax 调用 aspx 页面 Web 方法

c# - 加密异常 : Access denied - How to give access on User store?

wpf - WPF可编辑组合框验证

c# - 如何将 ObservableCollection<bool> 绑定(bind)到 WPF 中的复选框列表框

java - RxAndroid -BehaviorSubject 未在 onNext 上发出

C# - 如何在用户控件之间传输信息

c# - 如何最小化Windows中的内存使用

c# - 读取 PDF 文件并作为流从 WCF 服务返回?

适用于 Windows Phone : BindingExpression path error with user control - Property not found 的 Silverlight