Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(is there an) Easy way to check if property in (complex) pocomodel has changed?

Tags:

c#

I was wondering if there is an 'easy'/good way to check if a property has changed. Like in the hierarchy below when Child.Name has changed (isDirty) I would like to know.

GrantParent
- Parent
-- Child

In my current situation I need to navigate through the model to see if anything has changed.

ps: I'm using IChangeTracking.

Been thinking about caching a hash of the serialized object. (too slow?)

Or creating changedevent which call's the parent until it reaches the grantparent. (chatty?)

  public class Parent: BaseEntity
  {
    private Child _child;
    public Child Child
    {
      get { return _child; }
      set { _child = value; OnPropertyChanged("Child"); }
    }
  }

  public class Child : BaseEntity
  {
    private  int _id;
    public int Id {
      get { return _id; }
      set { _id = value; OnPropertyChanged("Id"); }
    }
  }



 [DataContract]
  [Serializable]
  public abstract class BaseEntity : INotifyPropertyChanged
  {
    protected BaseEntity()
    {
      PropertyChanged += PropertyChangedEventHandler;
    }

    private void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e)
    {
      if (e != null && !String.Equals(e.PropertyName, "IsChanged", StringComparison.Ordinal))
      {
        this.IsChanged = true;
      }
    }

    protected void OnPropertyChanged<T>(Expression<Func<T>> property)
    {
      MemberExpression me = property.Body as MemberExpression;
      if (me == null || me.Expression != property.Parameters[0]
            || me.Member.MemberType != MemberTypes.Property)
      {
        throw new InvalidOperationException(
            "Now tell me about the property");
      }
      var handler = PropertyChanged;
      if (handler != null) handler(this,
        new PropertyChangedEventArgs(me.Member.Name));
    }

    [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
    public bool IsChanged
    {
      get
      {
        lock (_notifyingObjectIsChangedSyncRoot)
        {
          return _notifyingObjectIsChanged;
        }
      }

      protected set
      {
        lock (_notifyingObjectIsChangedSyncRoot)
        {
          if (!Boolean.Equals(_notifyingObjectIsChanged, value))
          {
            _notifyingObjectIsChanged = value;

            if (IsDirtyChanged != null)
              IsDirtyChanged();

            this.OnPropertyChanged("IsChanged");
          }
        }
      }
    }

    private bool _notifyingObjectIsChanged;
    private readonly object _notifyingObjectIsChangedSyncRoot = new Object();

    public void AcceptChanges()
    {
      this.IsChanged = false;
    }
  }

In the end I used a compare on the XML model from the XML serializer I already used. I did't 'need' instant change detection once a second (or so) would be enough. Now I check the XML model with the one I had since the last save.

like image 935
Ralf de Kleine Avatar asked Dec 27 '25 16:12

Ralf de Kleine


1 Answers

You'll need to have each of the properties keep track of it themselves, and either store some information indicating what properties have changed, or possibly firing off an event when an item is changed.

essentially each property will have logic similar to this:

public class MyClass : INotifyPropertyChanged
{
    private int _value;
    public int Value
    {
        get
        {
            return _value;
        }
        set
        {
            _value = value;
            PropertyChanged(this, new PropertyChangedEventArgs("Value"));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

This will allow you to add an event handler to the PropertyChanged event so that code will be fired when a property is changed.

like image 54
Servy Avatar answered Dec 30 '25 05:12

Servy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!