0

我有一个与 UI 中的项目列表相关联的 observablecollection。(observablecollection 不绑定到 UI 中的项目)。

现在,用户可以选择多选项目并通过拖放重新排序。所以,如果我有项目 1、2、3、4、5、6、7、8。例如,用户选择 4、6、8 并选择在项目 1 和 2 之间插入,那么新的列表顺序将是,

1、4、6、8、2、3、5、7。

如何使用 Move() 函数一次更新列表?

如果我使用一次移动,列表已经处于不同的状态......?我应该在单独的数组中跟踪旧索引然后移动它们吗?这是最好的方法吗?感谢您的任何建议。

4

2 回答 2

1

如果您的目标是只提升一次 CollectionChanged 处理程序 - 您可以将 ObservableCollection 子类化(它不是密封的)并添加一个名为 RaiseCollectionChanged 的​​ bool 属性,在任何静默更新之前将其设置为 true。

在此集合中实际执行移动的方法是受保护的和虚拟的 - 因此您可以在调用 base.MoveItem(引发事件)之前覆盖并检查 RaiseCollectionChanged。

在静默模式下修改集合时维护一个标记的标志也是一个好主意。这样,当 RaiseCollectionChanged 再次设置为 true 时,您可以一次为所有修改的项目引发事件。

于 2012-05-29T13:56:02.747 回答
0

太长的帖子无法在评论中,所以在这里作为答案。
正如ananthonline发布的那样,您可以继承 ObservableCollection。

但是,不幸的是,这只是工作的一半。原因是集合隐式使用集合视图作为项目控制的项目源绑定。

而作为 WPF 中所有默认集合视图的基类型的CollectionView不支持批量集合更新:

private void ValidateCollectionChangedEventArgs(NotifyCollectionChangedEventArgs e)
{
    switch (e.Action)
    {
        case NotifyCollectionChangedAction.Add:
        {
            if (e.NewItems.Count != 1)
            {
                throw new NotSupportedException(SR.Get("RangeActionsNotSupported"));
            }
            break;
        }
        case NotifyCollectionChangedAction.Remove:
        {
            if (e.OldItems.Count != 1)
            {
                throw new NotSupportedException(SR.Get("RangeActionsNotSupported"));
            }
            if (e.OldStartingIndex < 0)
            {
                throw new InvalidOperationException(SR.Get("RemovedItemNotFound"));
            }
            break;
        }
        case NotifyCollectionChangedAction.Replace:
        {
            if (e.NewItems.Count != 1 || e.OldItems.Count != 1)
            {
                throw new NotSupportedException(SR.Get("RangeActionsNotSupported"));
            }
            break;
        }
        case NotifyCollectionChangedAction.Move:
        {
            if (e.NewItems.Count != 1)
            {
                throw new NotSupportedException(SR.Get("RangeActionsNotSupported"));
            }
            if (e.NewStartingIndex < 0)
            {
                throw new InvalidOperationException(SR.Get("CannotMoveToUnknownPosition"));
            }
            break;
        }
        case NotifyCollectionChangedAction.Reset:
        {
            break;
        }
        default:
        {
            throw new NotSupportedException(SR.Get("UnexpectedCollectionChangeAction", new object[]
            {
                e.Action
            }));
        }
    }
}

...并且您必须实现 ICollectionView。我不确定,这是正确的方法。

于 2012-05-29T18:25:11.910 回答