简体   繁体   中英

How to create my own PropertyChangedEventArgs for INotifyPropertyChanged interface?

I have come across an issue where i get in an endless loop between my DataModel and ViewModel with PropertyChanged event .

My structure:

public class SomeDataModel : DataModelBase
{
    public SomeDataModel()
    {

    }

    public object SomeProperty
    {
        get
        {
            //
        }
        set;
        {
            //
            OnPropertyChanged("SomeProperty");
        }
    }

    public bool SomeMethod()
    {
        SomeProperty = SomeNewObject
    }
}

public class SomeViewModel : ViewModelBase
{
    public SomeViewModel()
    {

    }

    public SomeDataModel SomeDataModel
    {
        get;
        set;
    }

    public object SomeProperty
    {
        get
        {
            return SomeDataModel.SomeProperty;
        }
        set
        {
            SomeDataModel.SomeProperty = value;
            OnPropertyChanged("SomeProperty");
        }
    }
}

Both ViewModel and DataModel implements INotifyPropertyChanged .

Then i have a listener in my ViewModelBase for any property that changes in my DataModel :

private void DataModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    PropertyInfo toPropertyInfo = this.GetType().GetProperty(e.PropertyName);
    PropertyInfo fromPropertyInfo = DataModel.GetType().GetProperty(e.PropertyName);

    if (toPropertyInfo != null && fromPropertyInfo != null)
    {
        if (toPropertyInfo.CanWrite && fromPropertyInfo.CanRead)
        {
            toPropertyInfo.SetValue(this, fromPropertyInfo.GetValue(DataModel, null), null);
        }
    }
}

So now when the property gets set in the DataModel , the listener in ViewModelBase catches it and updates the relevant property in the ViewModel . But the set in the ViewModel sets it back to the DataModel with causes OnPropertyChanged("SomeProperty"); to fire agian, ending in a endless loop.

  1. Is there a quick work around to fix it? ( Note : Can't change the structure)
  2. Would i be able to create my own custom class, inheriting from PropertyChangedEventArgs and still have my INotifyPropertyChanged operations working?

I was thinking:

public class CustomPropertyChangedEventArgs : PropertyChangedEventArgs
{
    public CustomPropertyChangedEventArgs(string propertyName, SomeEnum enumName)
        : base(propertyName)
    {
        //Set enum
    }
}

and then in OnPropertyChanged i want to use the new CustomPropertyChangedEventArgs and pass the enum in that i want to use.

public void OnPropertyChanged(string propertyName)
{
    CustomPropertyChangedEventArgs handler = this.PropertyChanged;

    if (handler != null)
    {
        handler(this, new CustomPropertyChangedEventArgs(propertyName, newEnum));
    }
}

You can check if the value is the same and don't update it. This is how usually INotifyPropertyChanged is implemented. You fire the OnPropertyChanged only if it really changed.

public object SomeProperty
{
    get
    {
        return SomeDataModel.SomeProperty;
    }
    set
    {
        if (SomeDataModel.SomeProperty != value)
        {
            SomeDataModel.SomeProperty = value;
            OnPropertyChanged("SomeProperty");
        }
    }
}
you can disable and enable the event to avoid loop
private void DataModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    OnPropertyChanged -= DataModel_PropertyChanged;
    PropertyInfo toPropertyInfo = this.GetType().GetProperty(e.PropertyName);
    PropertyInfo fromPropertyInfo = DataModel.GetType().GetProperty(e.PropertyName);

    if (toPropertyInfo != null && fromPropertyInfo != null)
    {
        if (toPropertyInfo.CanWrite && fromPropertyInfo.CanRead)
        {
            toPropertyInfo.SetValue(this, fromPropertyInfo.GetValue(DataModel, null), null);
        }
    }
    OnPropertyChanged += DataModel_PropertyChanged;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM