【问题标题】:object editing and isDirty() flag对象编辑和 isDirty() 标志
【发布时间】:2010-09-17 02:02:12
【问题描述】:

我正在开发一个系统,用户可以通过 GUI 编辑现有对象(准确地说是“过滤”域对象)。作为 UI 提示,我们只希望在用户确实修改了对象的某些内容时启用保存按钮。我想知道是否有人对这个问题有任何经验,以及解决这个问题的最佳方法是什么。

我正在考虑向域对象添加一个 isDirty() 标志。当用户开始编辑过滤器时,我会制作一个副本,将其传递给 GUI 并让用户对副本进行修改。然后,isDirty() 标志上的绑定将启用/禁用保存按钮。保存后,差异将被合并到原始对象中并保留。

另外,我在想如果用户撤消他对对象所做的更改会发生什么。然后 isDirty() 标志应该返回 false。所以我想实现这一点的唯一方法是将每个属性的原始值保留在域对象中。

有什么想法吗?

【问题讨论】:

    标签: user-interface dns flags


    【解决方案1】:

    正确!

    此外,您可以公开两种方法: BeginEdit - 在此方法中,您将 IsDirty 标志标记为 True。表示您正在修改。即将进行修改时调用此方法

    CancelEdit - 在此方法中,将 IsDirty 标志重置为 False。这意味着您已经中止了编辑过程并恢复到原始状态。取消任何修改时调用此方法。

    一旦任何修改被持久化,您还将 IsDirty 标志重置为 False。

    我希望这会有所帮助。

    【讨论】:

    • 感谢大家的回答。我接受了这个答案,因为它是第一个并且获得了最多的支持。
    • 这听起来很像 CSLA。如果您使用的是 .NET,我建议您检查一下。 lhotka.net
    【解决方案2】:

    如果您使用 .NET 框架,您可能想看看 Rockford Lhotka 的 CSLA .NET 框架:http://www.lhotka.net/cslanet/Default.aspx

    CSLA 是一个成熟的框架,包括对象状态管理 (IsDirty)、撤消功能、数据绑定等,而且它是免费和开源的。

    【讨论】:

      【解决方案3】:

      您可以实现几个接口来帮助跟踪和撤消更改:INotifyPropertyChanged 和 IEditableObject。这两个接口都允许对象很好地使用数据绑定。

      public class Person : INotifyPropertyChanged, IEditableObject
      {
          private bool isDirty;
      
          public bool IsDirty
          {
              get { return isDirty; }
          }
      
          private string firstname = string.Empty;
      
          public string Firstname
          {
              get { return firstname; }
              set
              {
                  if (firstname == value) return;
                  firstname = value;
                  NotifyPropertyChanged("Firstname");
              }
          }
      
          private string lastname = string.Empty;
      
          public string Lastname
          {
              get { return lastname; }
              set
              {
                  if (lastname == value) return;
                  lastname = value;
                  NotifyPropertyChanged("Lastname");
              }
          }
      
          public event PropertyChangedEventHandler PropertyChanged;
      
          public void NotifyPropertyChanged(string propertyName)
          {
              isDirty = true;
      
              if (PropertyChanged != null)
                  PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
          }
      
          private bool inTrans;
          private Person copy;
      
          public void BeginEdit()
          {
              if (!inTrans)
              {
                  if (copy == null)
                      copy = new Person();
      
                  copy.isDirty = isDirty;
                  copy.Firstname = Firstname;
                  copy.Lastname = Lastname;
      
      
                  inTrans = true;
                  isDirty = false;
              }
          }
      
          public void CancelEdit()
          {
              if (inTrans)
              {
                  isDirty = copy.isDirty;
                  Firstname = copy.Firstname;
                  Lastname = copy.Lastname;
      
                  inTrans = false;
              }
          }
      
          public void EndEdit()
          {
              if (inTrans)
              {
                  copy = null;
                  inTrans = false;
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        如果您有一组正在编辑的对象,那么您可能需要的不仅仅是 isDirty() 的布尔标志。这个问题与引用计数没有什么不同,即在编辑时增加脏计数,在撤消时减少。如果您支持撤消,我怀疑您最终会遇到一些非常多毛的逻辑。我会把它排除在你的域对象之外。

        【讨论】:

          【解决方案5】:

          是的,这很好用。我没有撤消,而是使用 IsDirty 方法来表示某些东西可能已经更改了记录,然后触发了我的“记录是否更改逻辑”。我开发了自己的框架,其中每个表字段实际上都是对象的属性。每次将字段写入对象时,都会设置“isDirty”标志。在对象的“SaveObject”方法中(实际上它是一个帮助类,但可以很容易地在对象中,但我希望能够以不同的方式保存对象,例如 xml、数据库等),我检查了 IsDirty 和如果它是假的,那么我会跳过保存。这简化了逻辑,因为每次我有可能更改对象时,我都会调用 SaveObject 并让框架处理它。

          【讨论】:

            【解决方案6】:

            根据您的域,您可以使用相等来测试差异。保留原始对象并复制对象以进行编辑。任何时候可以执行编辑,适当地修改 UI。

            这个建议的好处是它不会在您的域对象上粘贴 GUI 特定功能(isDirty() 标志),而是 YMMV

            【讨论】:

              【解决方案7】:

              如果您支持的操作撤消粒度大于“撤消自上次保存以来的所有内容”,那么我建议使用撤消堆栈。当某些东西被编辑时,它(或它的撤消操作函子或委托)被添加到堆栈中。当您撤消时,您只需弹出堆栈并撤消弹出的操作。然后,您的 isDirty() 标志只是检查撤消堆栈是否包含项目,而不是额外的存储和更新逻辑。

              【讨论】:

              • 感谢您的建议。我想知道撤消堆栈会在哪里。它是 UndoManager 中的一个单独对象还是某种类型的对象,其中堆栈链接到您正在编辑的域对象?
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-02-27
              相关资源
              最近更新 更多