7

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

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

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

有任何想法吗?

4

7 回答 7

3

正确的!

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

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

一旦任何修改被保留,您还将 IsDirty 标志重置为 False。

我希望这有帮助。

于 2008-10-14T12:12:32.573 回答
2

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

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

于 2008-10-14T12:25:16.277 回答
2

您可以实现几个接口来帮助进行更改跟踪和撤消: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;
        }
    }
}
于 2008-10-14T20:00:25.983 回答
1

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

于 2008-10-14T12:17:35.340 回答
1

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

于 2008-10-14T12:23:07.903 回答
1

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

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

于 2008-10-14T12:27:15.510 回答
1

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

于 2008-10-14T12:27:52.637 回答