【发布时间】:2012-07-13 09:48:38
【问题描述】:
我有一个具有撤消重做功能的 WPF 应用程序。我使用 EF 与数据库进行交互。
我想知道是否有更好的方法或模式可以在 UI 更改某些属性时得到通知。
这是我目前使用的方法:
-
让 EF 生成类。例如:
public partial class Page: IObjectWithChangeTracker, INotifyPropertyChanged { #region Primitive Properties [DataMember] public string title { get { return _title; } set { if (_title != value) { _title = value; OnPropertyChanged("title"); } } } private string _title; ... -
然后在类的非生成部分,我为 UI 添加另一个属性。在这种特殊情况下,该属性绑定到 WPF 文本框:
public partial class Page { public Page() { ((INotifyPropertyChanged)this).PropertyChanged += Page_PropertyChanged; } void Page_PropertyChanged(object sender, PropertyChangedEventArgs e) { switch (e.PropertyName) { case "title": OnPropertyChanged("titleUI"); break; } } public string titleUI { get { return title; } set { if (value == title) return; string oldValue = title; title = value; UndoRedo.PushAtomic( () => title = oldValue, () => title = value, "change page title"); } } ...
我曾经为此目的收听 FrameworkElement.SourceUpdated,但我放弃了这种方法以更紧密地遵循 MVVM 设计模式。
有没有更好或更简单的方法?
编辑: 我不直接将 TextBox 绑定到 title 属性的原因是,我不想在属性被某些东西更新时添加到 undo-redo 堆栈除了文本框。此外,当 EF ObjectContext 实现实体时,值由 setter 分配,我也不想将其添加到 undo-redo 堆栈中。
编辑 2: 对于这个问题,我有点放弃了。如果可以,我会删除它。例如,我无法理解关于我的代码不是真正的 MVVM 的 cmets 与手头的问题有什么关系。无论我是否将实体类与所谓的 ViewModel 类严格分开,我仍然必须找到一种方法来“拦截”来自 UI 的更新。我投票关闭。如果你和我一样觉得这无济于事,请也这样做。
【问题讨论】:
-
这里似乎是一种奇怪的方法 - 我是否正确,您有混合模型/视图模型?看起来 Page 是您的模型,但您只是通过使用部分将 Page 类扩展为您的 ViewModel?
-
是的,ViewModel 将是生成的类(即模型)的“扩展”。
-
好吧,从技术上讲,我不会称它为视图模型——它更像是一个丰富的模型——你不能绑定到 Title 属性有什么原因吗?由于您几乎正在制作一个丰富的模型,您不妨使用它的属性
-
看到这是我在使用 MVVM 时遇到的问题 - 事实上,您最终会在 VM 中重新实现所有内容。有些框架可以为您提供丰富的(生成的)模型,然后允许您通过 VM 公开它。通过这种方式,您可以绑定到模型上的属性,而不是在视图模型中重新实现它们。在您的情况下,可能值得使用 Unity/Ninject 之类的东西来挂钩属性更改事件 - 这样您就可以将代码注入到生成的代码中,而无需重新实现所有内容。我不喜欢这段代码的样子,它会让我头疼
-
@Charleh:我不得不问:为什么不能将类的文件分离视为模型/视图模型分离?你是根据什么做出这样的肯定的?
标签: c# .net wpf entity-framework mvvm