" Atomic Move" C#集合是否存在操作?

时间:2014-03-19 17:01:51

标签: c# wpf collections

假设我在带有ObservableCollection的WPF应用程序中有一个ViewModel。此集合与Model集合同步,以便更新任何一个更新另一个。该模型有一个业务规则,声明它必须始终包含2个Thing,但可以更改集合中的顺序。用户将看到一个包含两个Thing的列表,并且具有可以单击以向上或向下移动Thing的按钮。模型类订阅了它的集合变更处理程序,如果集合中的东西少于2件,则会抛出异常。

像这样的东西(非常简化,边缘情况不处理等)

public class ViewModel
{
    private Model _model;

    public ObservableCollection<Thing> Things { get; set; }
    public Thing SelectedThing { get; set; }

    public ViewModel(Model model)
    {
        _model = model;

        Things = new ObservableCollection<Thing>(_model.Things);
        // Some other code that ensures the model and viewmodel collections stay in sync
        // ...
    }

    public void MoveUp()
    {
        var selected = SelectedThing;

        int i = Things.IndexOf(selected);
        Things.Remove(selected); // Throws exception
        Things.Insert(i - 1, selected);
    }
}

public class Model
{
    public ObservableCollection<Thing> Things { get; set; }

    public Model()
    {
        Things = new ObservableCollection
        {
            new Thing(),
            new Thing()
        };

        Things.CollectionChanged += CollectionChangedHandler;
    }

    private void CollectionChangedHandler(object sender, CollectionChangedEventArgs e)
    {
        if(e.Action == CollectionChangedAction.Remove)
        {
            if(Things.Count < 2)
            {
                throw new YouCantDoThatException();
            }
        }
    }
}

基本上,当用户点击&#34;上移&#34;时,会暂时从集合中删除所选项目并将其插入到之前的位置。这是模型的无效状态,我无法更改模型,因为它是许多其他内容的API。在C#中是否有办法进行&#34; Atomic Move&#34;操作,这将允许我移动项目而不先删除它?

1 个答案:

答案 0 :(得分:3)

我看到两个选项:

  1. 使用&#34;移动&#34;由ObservableCollection提供的函数。缺点是您的代码处于只有一个项目的状态(尽管时间很短),但由于CollectionChanged不会被提升直到移动完成,因此您的异常不会抛出。

    < / LI>
  2. 反转逻辑,并在删除之前执行插入操作。您可以使用InsertItem(index,item)函数执行此操作,然后执行RemoveAt(index)命令。

  3. 一般来说,没有&#34; Atomic&#34;移动因为&#34;交换&#34;运作工作。你需要分配&#34;首先&#34;将值设置为临时值,将第二个值分配给第一个,然后将临时值分配给第二个。某些装配操作可以使这个&#34; Atomic&#34;从最纯粹的意义上说,但这对NotifyCollectionChanged没有帮助。

    另外,您可以从ObservableCollection派生并实现自己的移动算法,除非您需要Move才能拥有其他功能,否则您不应该这样做。 (MSDN)。