我遇到DomainContext.RejectChanges()的问题,并反映了UI中的回滚。这是我的情景。
所以基本上在一个屏幕上有一个 FooViewModels 列表框...当你选择一个项目时,会显示一个子窗口来编辑那个特定的 FooViewModel 。 FooViewModel 正在为列表框和子窗口提供服务。
编辑工作正常。子窗口的更改立即反映在列表框中,因为我在更新viewmodel属性时调用 RaisePropertyChanged()。
但是,如果我执行 DomainContext.RejectChanges() ...基础实体将被回滚(所有更改都按预期还原)...但 FooViewModel 我不知道发生了这种变化,因此UI没有更新。如果我在第一个屏幕上的列表框中重新选择该项目,则会显示子窗口,其中包含回滚的更改(这就是我想要的)。列表框仍然没有更新。
当我拒绝更改时,如果我 kludge RaiseProperyChanged(),我更改的字段... UI列表框会更新。
当基础实体被拒绝时,如何让UI更新?如何在不跟踪视图模型的哪些属性回滚的情况下执行此操作?必须有一种简单的方法来实现这一点,我才会失踪。
答案 0 :(得分:2)
您可以尝试的是使用基础实体Foo
上的PropertyChanged事件来触发FooViewModel
属性上的RaisePropertyChanged传递。
所以做出一些假设(所以这段代码有意义):
您的FooViewModel
中有私人变量
private Foo _foo;
private DomainContext _context;
您的FooViewModel
上有一个方法正在您的域上下文中调用RejectChanges()
。
像这样:
public void RejectChanges()
{
_context.RejectChanges();
}
FooViewModel
像这样:
private void RaisePropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if(handler != null)
handler(this, new PropertyChangedEventArgs(propertyName);
}
好的,现在我们已经确定了,让我们看看在域上下文中调用RejectChanges()
时会发生什么。
当您致电RejectChanges()
时,这会在DomainContext
到EntityContainer
,然后到该容器中的每个EntitySet
,然后到每个Entity
。集合。
一旦存在(并且在EntitySet
中),它会重新应用原始值(如果有的话),删除实体(如果已添加),或者添加实体(如果已删除)。如果值发生了变化,则会将它们应用回属性。
理论上,应该触发在实体属性中生成的所有RaisePropertyChanged()。
注意:我实际上没有测试过这个。如果情况并非如此,那么这一切都不起作用:P
因此,我们可以挂钩Foo
实体的PropertyChanged事件,并在PropertyChanged
上引发FooViewModel
事件。
所以我们的RejectChanges()
方法可能如下所示:
public void RejectChanges()
{
Func<object, PropertyChangedEventArgs> handler = (sender, e) =>
{
RaisePropertyChanged(e.PropertyName);
};
_foo.PropertyChanged += handler;
_context.RejectChanges();
_foo.PropertyChanged -= handler;
}
因此,我们将事件处理程序连接到我们的Foo
实体,该实体使用FooViewModel.RaisePropertyChanged
实体上正在更改的属性名称调用Foo
方法。
然后我们拒绝更改(触发属性更改),
然后我们取消了事件处理程序。相当长的啰嗦,但我希望这会有所帮助:)
答案 1 :(得分:0)
我认为对DomainContext.RejectChanges()
的调用发生在ViewModel
内,因为您可能将其绑定到从父ViewModel
调用的某个命令或方法。由于所有对数据的绑定都是在ViewModel
属性上完成的,因此当您直接在这些属性之外操作模型时,必须在它们上引发属性更改事件。你可能已经做过了。
public void RejectChanges()
{
DomainContext.RejectChanges();
RaisePropertyChangeOnAll();
}
如何通过每个属性的RaisePropertyChangeOnAll()
列表简单地实现RaisePropertyChange("...")
,或者通过反射(如果Silverlight权限允许,不太确定)通过添加属性来实现RaisePropertyChanged
在您想要筹集的每个房产上。找到所有使用它标记的属性,并在MemberInfo.Name
值上调用[Raiseable]
public string SomeValue
{
...
}
。
{{1}}
只是一个想法,但可能不是一个完美的解决方案。