0

I have an object with five properties and each of these properties has two states ("before" and "after").

How do I get the information about which properties changed their state?

The only way that I am familiar with is to get a list of all the properties (using Reflection?), then use a loop to compare each property between two objects and store information about those which were changed.

Is there a simple way to do it, perhaps using LINQ?

vgru
  • 49,838
  • 16
  • 120
  • 201
  • [INotifyPropertyChanged Interface](http://msdn.microsoft.com/en-us/library/system.componentmodel.inotifypropertychanged(v=vs.110).aspx) – EZI Jul 05 '14 at 20:07
  • @EZI-Ive already read about it but didnt understand how it can help me since how I can I get just the property that was changed,for example if just f2 and f3 was changed... –  Jul 05 '14 at 20:12
  • @M.Herbert Not sure why you tagged this LINQ – Sascha Jul 05 '14 at 20:27

2 Answers2

1

The interface INotifyProprtyChanged requires you to implement an event PropertyChanged. You can subscribe to this interface in the class itself and track properties for which they get called.

For example:

internal class SampleClass : INotifyPropertyChanged{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _SampleProperty;
    internal List<string> _ChangedProperties;

    public SampleClass() {
      this.PropertyChanged += SampleClass_PropertyChanged;
      _ChangedProperties = new List<string>();
    }

    protected virtual void OnPropertyChanged( string propertyName ) {
          PropertyChangedEventHandler handler = PropertyChanged;
          if ( handler != null )
            handler( this, new PropertyChangedEventArgs( propertyName ) );
    }

    void SampleClass_PropertyChanged( object sender, PropertyChangedEventArgs e ) {
      if ( _ChangedProperties.Contains( e.PropertyName ) ) return;
      _ChangedProperties.Add( e.PropertyName );
    }

    public string SampleProperty {
      get { return _SampleProperty; }
      set {
        if (_SampleProperty == value )
          return;
        _SampleProperty = value;
        OnPropertyChanged( "SampleProperty" );
      }
    }
}

Now you have a list of changed properties. You can work further by remembering values, etc.

I have not considered thread safety, I would not consider this sample production ready.

Sascha
  • 10,231
  • 4
  • 41
  • 65
  • A common convention for classes exposing events is to implement a protected virtual method with a `On` prefix (i.e. `OnPropertyChanged` in this case) which actually invokes the event when called. It reduces code duplication (null-checks on each call) and removes the need for a class to attach to its own handles (all event-related functionality can be implemented inside that method). – vgru Jul 05 '14 at 20:37
  • @Groo Sure thing - exactly another reason why I mentioned this sample is not production code. Will update my question though – Sascha Jul 05 '14 at 20:39
  • @Sascha-thanks voted up,I surely try it up,my question is assume I i've F1-F10 fields,do I need to do it for all fields (What you did for sample property?or there is shorter way to do that?2.Assume that I've Obj1 and object2 from the same class,this is the best way to find the properties that was changed? –  Jul 05 '14 at 20:49
  • You can also do: `void OnPropertyChanged([CallerMemberName] string propertyName = "")`, then call: `OnPropertyChanged()` directly. Check this: http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute(v=vs.110).aspx for more details :D – user3439065 Jul 05 '14 at 20:50
  • @M.Herbert You need to support the `INotifyPropertyChanged` mechanisms on all fields. Each class contains the changed fields for itself, if you want to track it against another object than you need to compare – Sascha Jul 07 '14 at 05:35
1

You can do something like this:

public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);
public class PropertyChangedEventArgs : EventArgs
{
    public PropertyChangedEventArgs(string propertyName, dynamic oldValue, dynamic newValue)
    {
        this.PropertyName = propertyName;
        this.OldValue = oldValue;
        this.NewValue = newValue;
    }

    public virtual string PropertyName { get; private set; }
    public virtual dynamic OldValue { get; private set; }
    public virtual dynamic NewValue { get; private set; }
}

public class PropertyClass
{
    public event PropertyChangedEventHandler PropertyChanged;

    private void Set<T>(string propertyName, ref T field, T value)
    {
        if (field.Equals(value))
            return;

        T oldValue = value;
        field = value;

        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName, oldValue, value));
    }

    // Properties
    private string _name;
    private string _message;
    private bool _isMember;

    public string Name
    {
        get { return _name; }
        set { Set("Name", ref _name, value); }
    }

    public string Message
    {
        get { return _message; }
        set { Set("Message", ref _message, value); }
    }

    public bool IsMember
    {
        get { return _isMember; }
        set { Set("IsMember", ref _isMember, value); }
    }
}
user3439065
  • 840
  • 5
  • 8