Catel.MVVM.ViewModelBase.OnPropertyChanged C# (CSharp) Method

OnPropertyChanged() protected method

Called when a property value has changed.
protected OnPropertyChanged ( AdvancedPropertyChangedEventArgs e ) : void
e AdvancedPropertyChangedEventArgs The instance containing the event data.
return void
        protected override void OnPropertyChanged(AdvancedPropertyChangedEventArgs e)
        {
            if (IsSaving || IsCanceling || IsClosing || IsClosed)
            {
                return;
            }

            if (string.IsNullOrEmpty(e.PropertyName))
            {
                return;
            }

            lock (_modelLock)
            {
                if (_modelObjects.ContainsKey(e.PropertyName))
                {
                    // Clean up old model
                    var oldModelValue = _modelObjects[e.PropertyName];
                    if (oldModelValue != null)
                    {
                        UninitializeModelInternal(e.PropertyName, oldModelValue, ModelCleanUpMode.CancelEdit);
                    }

                    var newModelValue = GetValue(e.PropertyName);
                    _modelObjects[e.PropertyName] = newModelValue;

                    if (newModelValue != null)
                    {
                        InitializeModelInternal(e.PropertyName, newModelValue);
                    }

                    // Since the model has been changed, copy all values from the model to the view model
                    foreach (KeyValuePair<string, ViewModelToModelMapping> viewModelToModelMap in _viewModelToModelMap)
                    {
                        ViewModelToModelMapping mapping = viewModelToModelMap.Value;
                        IViewModelToModelConverter converter = mapping.Converter;
                        if (string.CompareOrdinal(mapping.ModelProperty, e.PropertyName) == 0)
                        {
                            var values = new object[mapping.ValueProperties.Length];
                            if (newModelValue != null)
                            {
                                // We have a new model, ignore OneWayToSource
                                if (mapping.Mode == ViewModelToModelMode.OneWayToSource)
                                {
                                    continue;
                                }

                                for (var index = 0; index < mapping.ValueProperties.Length; index++)
                                {
                                    var property = mapping.ValueProperties[index];
                                    values[index] = PropertyHelper.GetPropertyValue(newModelValue, property, false);
                                }
                            }
                            else
                            {
                                var property = mapping.ViewModelProperty;
                                var propertyData = GetPropertyData(property);
                                values[0] = propertyData.GetDefaultValue();
                            }

                            values[0] = converter.Convert(values, this);

                            SetValue(mapping.ViewModelProperty, values[0], true, ValidateModelsOnInitialization);
                        }
                    }
                }
            }

            // If we are validating, don't map view model values back to the model
            if (!IsValidating)
            {
                if (_viewModelToModelMap.ContainsKey(e.PropertyName))
                {
                    lock (_modelLock)
                    {
                        var mapping = _viewModelToModelMap[e.PropertyName];
                        var model = _modelObjects[mapping.ModelProperty];
                        if (model != null)
                        {
                            var modelInfo = _modelObjectsInfo[mapping.ModelProperty];
                            if (!modelInfo.IsCanceling)
                            {
                                var viewModelValue = GetValue(e.PropertyName);
                                var propertiesToSet = mapping.ValueProperties;

#if !WINDOWS_PHONE && !NET35 && !XAMARIN_FORMS
                                if (_modelErrorInfo.ContainsKey(mapping.ModelProperty))
                                {
                                    mapping.ValueProperties.ForEach(_modelErrorInfo[mapping.ModelProperty].ClearDefaultErrors);
                                }
#endif

                                // Only TwoWay, OneWayToSource mappings should be mapped
                                if ((mapping.Mode == ViewModelToModelMode.TwoWay) || (mapping.Mode == ViewModelToModelMode.OneWayToSource))
                                {
                                    var valuesToSet = mapping.Converter.ConvertBack(viewModelValue, this);
                                    if (propertiesToSet.Length != valuesToSet.Length)
                                    {
                                        Log.Error("Properties - values count mismatch, properties '{0}', values '{1}'",
                                            string.Join(", ", propertiesToSet), string.Join(", ", valuesToSet));
                                    }
                                    for (int index = 0; index < propertiesToSet.Length && index < valuesToSet.Length; index++)
                                    {
                                        if (PropertyHelper.TrySetPropertyValue(model, propertiesToSet[index], valuesToSet[index], false))
                                        {
                                            Log.Debug("Updated property '{0}' on model type '{1}' to '{2}'", propertiesToSet[index], model.GetType().Name, ObjectToStringHelper.ToString(valuesToSet[index]));
                                        }
                                        else
                                        {
                                            Log.Warning("Failed to set property '{0}' on model type '{1}'", propertiesToSet[index], model.GetType().Name);
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            Log.Warning("Value for model property '{0}' is null, cannot map properties from view model to model", mapping.ModelProperty);
                        }
                    }
                }
            }

            if (InvalidateCommandsOnPropertyChanged)
            {
                ViewModelCommandManager.InvalidateCommands();
            }
        }