Example #1
0
        /// <summary>
        /// This method must be used in derived objects next way: set { SetNotifyingProperty(() => PropertyName, ref fieldForPropertyName, value); }
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expressionWithPropertyName"></param>
        /// <param name="fieldForPropertyName"></param>
        /// <param name="value"></param>
        protected void SetNotifyingProperty <T>(Expression <Func <T> > expressionWithPropertyName, ref T fieldForPropertyName, T value)
        {
            if (!fieldForPropertyName.EqualsWithNullHandling(value))
            {
                T oldValue = fieldForPropertyName;
                fieldForPropertyName = value;
                string             propertyName;
                PropertyEventsPath currentPropertyEventsPath;
                if (_propertiesEvents != null)
                {
                    propertyName = expressionWithPropertyName.GetBodyMemberName();
                    if (_propertiesEvents.TryGetValue(propertyName, out currentPropertyEventsPath))
                    {
                        if (oldValue == null)
                        {
                            if (currentPropertyEventsPath.PropertiesEvents != null)
                            {
                                try
                                {
                                    INotifyingObject newValNotifyingObj = (INotifyingObject)value;
                                    newValNotifyingObj.SetPropertiesEvents(MergePropertyEventsPaths(newValNotifyingObj.GetPropertiesEvents(), currentPropertyEventsPath.PropertiesEvents));
                                }
                                catch (InvalidCastException ex)
                                {
                                    throw new InvalidOperationException(string.Format("Early handlers were subscribed to child properties: \"{0}\" "
                                                                                      + "but it's a violating operation because  a parent property \"{1}\" doesn't implement \"{3}\"",
                                                                                      string.Join(", ", currentPropertyEventsPath.PropertiesEvents.Select(pair => string.Format("{0}: {1}", pair.Key, pair.Value)).ToArray()),
                                                                                      propertyName, typeof(INotifyingObject), ex));
                                }
                                currentPropertyEventsPath.PropertiesEvents = null;
                                if (currentPropertyEventsPath.Events == null)
                                {
                                    _propertiesEvents.Remove(propertyName);
                                }
                            }
                        }

                        if (currentPropertyEventsPath.Events != null)
                        {
                            ChangedEventArgs <T> e = new ChangedEventArgs <T>(oldValue, value);
                            foreach (ChangedEventHandler <T> changedEventHandler in currentPropertyEventsPath.Events)
                            {
                                changedEventHandler(this, e);
                            }
                            return;
                        }
                    }
                }
                else
                {
                    currentPropertyEventsPath = null;
                    propertyName = null;
                }

                INotifyingObject oldValNotifyingObj = oldValue as INotifyingObject;
                if (oldValNotifyingObj != null)
                {
                    oldValNotifyingObj.ChildrenChanged -= OnChildrenChanged;
                }
                if (value != null)
                {
                    INotifyingObject newValNotifyingObj = value as INotifyingObject;
                    if (newValNotifyingObj != null)
                    {
                        newValNotifyingObj.ChildrenChanged += OnChildrenChanged;
                    }
                }
                else
                {
                    var oldValNotifyingObjPropertiesEvents = oldValNotifyingObj.GetPropertiesEvents();
                    if (oldValNotifyingObjPropertiesEvents != null)
                    {
                        if (currentPropertyEventsPath == null)
                        {
                            currentPropertyEventsPath = new PropertyEventsPath {
                                PropertiesEvents = oldValNotifyingObjPropertiesEvents
                            };
                            if (propertyName == null)
                            {
                                propertyName = expressionWithPropertyName.GetBodyMemberName();
                            }
                            _propertiesEvents.Add(propertyName, currentPropertyEventsPath);
                        }
                        else
                        {
                            currentPropertyEventsPath.PropertiesEvents = MergePropertyEventsPaths(currentPropertyEventsPath.PropertiesEvents, oldValNotifyingObjPropertiesEvents);
                        }
                    }
                }
                OnChildrenChanged(this, null);
            }
        }