0

我有一个具有撤消重做功能的 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属性的原因是我不想在属性被TextBox以外的其他东西更新时添加到撤消重做堆栈。此外,当 EF ObjectContext 实现实体时,值由设置器分配,我也不想将其添加到撤消重做堆栈中。

编辑2:对于这个问题,我有点放弃了。如果可以,我会删除它。例如,我无法理解关于我的代码不是真正的 MVVM 的评论与手头的问题有什么关系。无论我是否将实体类与所谓的 ViewModel 类严格分开,我仍然必须找到一种方法来“拦截”来自 UI 的更新。我投票关闭。如果你和我一样觉得这无济于事,请做同样的事情。

4

2 回答 2

1

wpf 文本框有一个内置的撤消/重做 - 所以如果你只是将你的 viewmodel 属性与 mode=twoway 绑定,你的 viewmodel 和你的视图总是同步的,你的文本框处理重做撤消。我想念什么吗?

于 2012-07-13T10:35:59.943 回答
0

不是你想要的答案,但我会看看 Unity 之类的东西:

http://blogs.msdn.com/b/agile/archive/2011/03/21/interception-in-silverlight-demo.aspx

这是一篇 silverlight 帖子(但它也适用于 WPF 等)。基本上,您可以为您的模型创建一个拦截器并将代码注入属性 getter/setter。这样您就可以调用您的 N 级撤消/重做处理代码,而无需重新实现属性。

您所做的仍然看起来更像是一个富模型而不是视图模型,因为标准视图模型会封装模型

我不想为模型上的每个属性编写一个带有该代码的附加属性 getter/setter

(他们展示了一个虚拟方法拦截器,但可以使用实例拦截器,我认为这会起作用,但听听他们对拦截器的看法以及他们“监听”的范围)

编辑:

抱歉没有真正回答问题

以下是一些建议:

我不确定 EF 是否让您的实体类派生自基类,但这将是一件事 - 您只需在基类中挂钩 PropertyChanged 事件并进行相应处理。您可以Dictionary<string, object>在基础上保留 a 以跟踪“旧”值并处理撤消

我了解有关 EF 物化对象的一点 - 你能不能在 UndoRedo 堆栈上添加一个标志,告诉它在物化对象时忽略任何属性更改?

必须有一些方法可以在部分实体类中覆盖,以告诉堆栈绕过任何撤消/重做信息

于 2012-07-13T10:05:35.310 回答