对象编辑和 isDirty() 标志

发布于 2024-07-06 11:48:33 字数 377 浏览 5 评论 0原文

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

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

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

有任何想法吗?

I'm working on a system were a user can edit existing objects ("Filter" domain objects to be exact) through a GUI. As a UI hint, we only want to enable the save button if the user really modified something to the object. I was wondering if anyone had any experience with this problem and what the best way would be to approach this.

I was thinking about adding an isDirty() flag to the domain object. When a user starts editing a Filter, I would then make a copy, pass it to the GUI and let the user make modifications to the copy. A binding on the isDirty() flag would then enabled/disable the save button. On saving, the differences would then be merged into the original object and persisted.

Additionaly, I was thinking what would happen if a user undos the changes he made to an object. The isDirty() flag should then return false. So I guess the only way to achieve this is to keep the original value of each property inside the domain object.

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

梦里南柯 2024-07-13 11:48:33

正确的!

此外,您可以公开两种方法:
BeginEdit - 在此方法中,您将 IsDirty Flag 标记为 True。 意思是你正在做修改。 当您要进行修改时调用此方法

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

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

我希望这有帮助。

Correct!

Additionally,you can expose two methods:
BeginEdit - In this method, your mark your IsDirty Flag to True. Meaning you are doing modification. Call this method when you are about to make modifications

CancelEdit - In this method, reset the IsDirty Flag to False. Meaning you have arborted the edit process and reverted back to the original state. Call this method when cancelling any modifications made.

And once any modifications are persisted, you also reset the IsDirty Flag to False.

I hope this helps.

白云悠悠 2024-07-13 11:48:33

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

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

If you are using .NET framework, you may want to take a look at CSLA .NET framework by Rockford Lhotka: http://www.lhotka.net/cslanet/Default.aspx

CSLA is a mature framework which includes object state management (IsDirty), undo functionality, data binding and a lot more, plus it is free and open-source.

熊抱啵儿 2024-07-13 11:48:33

您可以实现几个接口来帮助跟踪和撤消更改: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;
        }
    }
}

There are a couple of interfaces that you could implement that help with change tracking and undo: INotifyPropertyChanged and IEditableObject. Both of these interfaces allow the object to play nice with databinding.

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;
        }
    }
}
永不分离 2024-07-13 11:48:33

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

If you have a set of objects which are being edited then you'll probably need something more than a boolean flag for isDirty(). This problem is not dissimilar to reference counting, i.e. increment a dirty count on edit and decrement on undo. If you are supporting undo I suspect you are going to wind up with some pretty hairy logic. I would keep it out of your domain objects.

完美的未来在梦里 2024-07-13 11:48:33

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

Yes, this works well. Rather than undo, I use the IsDirty method to signify that something MIGHT have changed the record and then that triggers my "did the record change logic". I developed my own framework, where every table field is actually a property of an object. Each time a field is written to the objects "isDirty" flag is set. In the "SaveObject" method of the object (actually its a helper class but could easily be in the object, but I wanted the ability to save objects in different manners, like to xml, database, ect.), I check the IsDirty and if its false then I skip the save. This simplifies the logic as each time I had the possibility of changing the object, I call SaveObject and let the framework handle it.

稀香 2024-07-13 11:48:33

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

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

Depending on your domain, you could use equality to test for differences. Keep the original object and make a copy of the object for editing. Anytime an edit may be performed, modify the UI appropriately.

The benefit of this suggestion is that it doesn't stick GUI specific functionality (the isDirty() flag) on your domain objects, but YMMV

智商已欠费 2024-07-13 11:48:33

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

If you are supporting operation undo at a level of granularity greater than 'undo everything since last save' then I'd suggest an undo stack. When something is edited, it (or it's undo operation functor or delegate) get's added to the stack. When you undo, you simply pop the stack and undo the operation popped. Your isDirty() flag is then just a check if the undo stack contains items, rather than extra storage and logic to update.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文