假设我在带有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;操作,这将允许我移动项目而不先删除它?
答案 0 :(得分:3)
我看到两个选项:
使用&#34;移动&#34;由ObservableCollection提供的函数。缺点是您的代码处于只有一个项目的状态(尽管时间很短),但由于CollectionChanged不会被提升直到移动完成,因此您的异常不会抛出。
< / LI>反转逻辑,并在删除之前执行插入操作。您可以使用InsertItem(index,item)函数执行此操作,然后执行RemoveAt(index)命令。
一般来说,没有&#34; Atomic&#34;移动因为&#34;交换&#34;运作工作。你需要分配&#34;首先&#34;将值设置为临时值,将第二个值分配给第一个,然后将临时值分配给第二个。某些装配操作可以使这个&#34; Atomic&#34;从最纯粹的意义上说,但这对NotifyCollectionChanged没有帮助。
另外,您可以从ObservableCollection派生并实现自己的移动算法,除非您需要Move才能拥有其他功能,否则您不应该这样做。 (MSDN)。