PropertyChanged Event Not Bubbling Up C#

两盒软妹~` 提交于 2019-12-08 10:50:52

问题


I'm designing a simple model that can be edited on a screen. In this case, it's for Xamarin Forms UWP, but this model class is platform agnostic, and I doubt that it's a UWP/Xamarin specific problem. I need the code to work so that if I edited any property in the model, the event should bubble up to the top, and I should be able to handle the PropertyChanged event on UserPreferences to save the record. But, this event never gets fired no matter which properties are changed. I can see that the properties are getting changed.

If I instantiate the UserPreferences class with its normal constructor this works fine. But, this class is actually created with deserialization. So, it seems that the serialization process is doing something funny with the constructors.

Here are my classes:

[Serializable]
public class TaskNotificationPreferences : INotifyPropertyChanged
{
    #region Events 
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region Public Properties 
    public ObservableCollection<int> PriorityKeys { get; set; }
    #endregion

    #region Constructor 
    public TaskNotificationPreferences()
    {
        PriorityKeys = new ObservableCollection<int>();
        PriorityKeys.CollectionChanged += PriorityKeys_CollectionChanged;
    }
    #endregion

    #region Event Handlers 
    private void PriorityKeys_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PriorityKeys)));
    }
    #endregion
}

[Serializable]
public class NotificationPreferences : INotifyPropertyChanged
{
    #region Fields
    private bool _ReceivePushNotifications;
    private bool _ReceiveEmails;
    #endregion

    #region Events
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region Constructor 
    public NotificationPreferences()
    {
        TaskNotificationPreferences = new TaskNotificationPreferences();
        TaskNotificationPreferences.PropertyChanged += TaskNotificationPreferences_PropertyChanged;
    }
    #endregion

    #region Event Handlers 
    private void TaskNotificationPreferences_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TaskNotificationPreferences)));
    }
    #endregion

    #region Public Properties
    public TaskNotificationPreferences TaskNotificationPreferences { get; set; }

    public bool ReceivePushNotifications
    {
        get
        {
            return _ReceivePushNotifications;
        }
        set
        {
            _ReceivePushNotifications = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReceivePushNotifications)));
        }
    }

    public bool ReceiveEmails
    {
        get
        {
            return _ReceiveEmails;
        }
        set
        {
            _ReceiveEmails = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReceiveEmails)));
        }
    }
    #endregion
}

[Serializable]
public class UserPreferences : INotifyPropertyChanged
{
    #region Events 
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region Public Properties 
    public NotificationPreferences NotificationPreferences { get; set; }
    #endregion

    #region Constructor 
    public UserPreferences()
    {
        NotificationPreferences = new NotificationPreferences();
        NotificationPreferences.PropertyChanged += NotificationPreferences_PropertyChanged;
    }
    #endregion

    #region Event Handlers 
    private void NotificationPreferences_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NotificationPreferences)));
    }
    #endregion
}

How the class is being deserialized:

    public static SerialiseType DeserialiseObjectWithoutCatch<SerialiseType>(string objectXml)
    {
        var serializer = new XmlSerializer(typeof(SerialiseType));
        var sr = new StringReader(objectXml);
        var retVal = serializer.Deserialize(sr);
        return (SerialiseType)retVal;
    }

Edit: In the end, this is the workaround I got to. It works, but I think that to some extent it highlights the problem with serialization in .NET. Here is my workaround code:

[Serializable]
public class UserPreferences : INotifyPropertyChanged
{
    #region Events 
    public event PropertyChangedEventHandler PropertyChanged;
    #endregion

    #region Public Properties 
    public NotificationPreferences NotificationPreferences { get; set; } = new NotificationPreferences();
    #endregion

    #region Event Handlers 
    private void NotificationPreferences_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(NotificationPreferences)));
    }
    #endregion

    #region Public Methods
    public void HandlePropertyChanged()
    {
        NotificationPreferences.PropertyChanged += NotificationPreferences_PropertyChanged;
        NotificationPreferences.HandlePropertyChanged();
    }
    #endregion
}


   [Serializable]
    public class NotificationPreferences : INotifyPropertyChanged
    {
        #region Fields
        private bool _ReceivePushNotifications;
        private bool _ReceiveEmails;
        #endregion

        #region Events
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        #region Event Handlers 
        private void TaskNotificationPreferences_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TaskNotificationPreferences)));
        }
        #endregion

        #region Public Properties
        public TaskNotificationPreferences TaskNotificationPreferences { get; set; } = new TaskNotificationPreferences();

        public bool ReceivePushNotifications
        {
            get
            {
                return _ReceivePushNotifications;
            }
            set
            {
                _ReceivePushNotifications = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReceivePushNotifications)));
            }
        }

        public bool ReceiveEmails
        {
            get
            {
                return _ReceiveEmails;
            }
            set
            {
                _ReceiveEmails = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ReceiveEmails)));
            }
        }
        #endregion

        #region Public Methods
        internal void HandlePropertyChanged()
        {
            TaskNotificationPreferences.PropertyChanged += TaskNotificationPreferences_PropertyChanged;
            TaskNotificationPreferences.HandlePropertyChanged();
        }
        #endregion
    }


   [Serializable]
    public class TaskNotificationPreferences : INotifyPropertyChanged
    {
        #region Events 
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

        private ObservableCollection<int> _PriorityKeys = new ObservableCollection<int>();

        #region Public Properties 
        public ObservableCollection<int> PriorityKeys
        {
            get { return _PriorityKeys; }
            set
            {
                _PriorityKeys = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PriorityKeys)));
            }
        }
        #endregion

        #region Event Handlers 
        private void PriorityKeys_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PriorityKeys)));
        }
        #endregion

        #region Public Methods
        internal void HandlePropertyChanged()
        {
            PriorityKeys.CollectionChanged += PriorityKeys_CollectionChanged;
        }
        #endregion

    }

So, my question really is now, what is the best way to deal with this? Is this a bug in .NET? A bug in serialization? Or, should the model be redesigned somehow?

来源:https://stackoverflow.com/questions/46292590/propertychanged-event-not-bubbling-up-c-sharp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!