protected override bool SetValueInternal(IBindingSourceAccessor targetAccessor, IDataContext context, bool throwOnError) { IBindingPathMembers members = _bindingSource.GetPathMembers(throwOnError); if (!members.AllMembersAvailable) { return(false); } object penultimateValue = members.PenultimateValue; IBindingMemberInfo lastMember = members.LastMember; object oldValue; object newValue = targetAccessor.GetValue(lastMember, context, throwOnError); if (lastMember.CanRead && !BindingMemberType.BindingContext.EqualsWithoutNullCheck(lastMember.MemberType)) { oldValue = lastMember.GetValue(penultimateValue, null); if (ReferenceEquals(oldValue, newValue) || newValue.IsUnsetValueOrDoNothing()) { return(false); } } else { oldValue = BindingConstants.UnsetValue; if (newValue.IsUnsetValueOrDoNothing()) { return(false); } } ValueAccessorChangingEventArgs args = null; if (ValueChanging != null) { args = RaiseValueChanging(context, penultimateValue, lastMember, oldValue, newValue); if (args != null) { if (args.Cancel) { return(false); } if (!ReferenceEquals(newValue, args.NewValue)) { newValue = args.NewValue; if (newValue.IsUnsetValueOrDoNothing()) { return(false); } } } } newValue = BindingServiceProvider.ValueConverter(lastMember, lastMember.Type, newValue); if (Equals(oldValue, newValue)) { return(false); } if (BindingMemberType.Event.EqualsWithoutNullCheck(lastMember.MemberType)) { TryRegisterEvent((BindingActionValue)oldValue, newValue, context); RaiseValueChanged(context, penultimateValue, lastMember, oldValue, newValue, args); } else { if (_closure != null) { _closure.Unsubscribe(false, _isOneTime); } lastMember.SetSingleValue(penultimateValue, newValue); if (ValueChanged != null) { RaiseValueChanged(context, penultimateValue, lastMember, oldValue, newValue, args); } } return(true); }
protected override bool SetValueInternal(IBindingSourceAccessor targetAccessor, IDataContext context, bool throwOnError) { IBindingPathMembers members = _bindingSource.GetPathMembers(throwOnError); object penultimateValue = members.PenultimateValue; if (penultimateValue.IsUnsetValue() || (penultimateValue == null && !members.AllMembersAvailable)) { if (members.Path.IsDebuggable) { DebugInfo($"Binding cannot set value for path {members.Path.Path}", new object[] { members }); } return(false); } IBindingMemberInfo lastMember = members.LastMember; object oldValue; object newValue = targetAccessor.GetValue(lastMember, context, throwOnError); if (lastMember.CanRead && !BindingMemberType.BindingContext.EqualsWithoutNullCheck(lastMember.MemberType)) { if (_disableEqualityChecking && !BindingMemberType.Event.EqualsWithoutNullCheck(lastMember.MemberType)) { oldValue = BindingConstants.UnsetValue; } else { oldValue = lastMember.GetValue(penultimateValue, null); } if (ReferenceEquals(oldValue, newValue) || newValue.IsUnsetValueOrDoNothing()) { if (members.Path.IsDebuggable) { DebugInfo($"Binding ignores setter because old value: '{oldValue}' equals to new value '{newValue}'", new[] { members, oldValue, newValue }); } return(false); } } else { oldValue = BindingConstants.UnsetValue; if (newValue.IsUnsetValueOrDoNothing()) { if (members.Path.IsDebuggable) { DebugInfo($"Binding ignores setter for value '{newValue}'", new[] { members, newValue }); } return(false); } } ValueAccessorChangingEventArgs args = null; if (ValueChanging != null) { args = RaiseValueChanging(context, penultimateValue, lastMember, oldValue, newValue); if (args != null) { if (args.Cancel) { return(false); } if (!ReferenceEquals(newValue, args.NewValue)) { newValue = args.NewValue; if (newValue.IsUnsetValueOrDoNothing()) { if (members.Path.IsDebuggable) { DebugInfo($"Binding ignores setter for value '{newValue}'", new[] { members, newValue }); } return(false); } } } } newValue = BindingServiceProvider.ValueConverter(lastMember, lastMember.Type, newValue); if (Equals(oldValue, newValue)) { if (members.Path.IsDebuggable) { DebugInfo($"Binding ignores setter because old value: '{oldValue}' equals to new value '{newValue}'", new[] { members, oldValue, newValue }); } return(false); } if (BindingMemberType.Event.EqualsWithoutNullCheck(lastMember.MemberType)) { TryRegisterEvent((BindingActionValue)oldValue, newValue, context, members); RaiseValueChanged(context, penultimateValue, lastMember, oldValue, newValue, args); } else { _closure?.Unsubscribe(false, _isOneTime); lastMember.SetSingleValue(penultimateValue, newValue); if (members.Path.IsDebuggable) { DebugInfo($"Binding set value: '{newValue}' for source: '{penultimateValue}' with path: '{lastMember.Path}'", new[] { newValue, penultimateValue, lastMember }); } if (ValueChanged != null) { RaiseValueChanged(context, penultimateValue, lastMember, oldValue, newValue, args); } } return(true); }
protected virtual IBindingMemberInfo GetExplicitBindingMember([NotNull] Type sourceType, [NotNull] string path) { path = path.Trim(); string[] indexerArgs = null; if (path.StartsWith("[", StringComparison.Ordinal) && path.EndsWith("]", StringComparison.Ordinal)) { indexerArgs = path .RemoveBounds() .Split(BindingReflectionExtensions.CommaSeparator, StringSplitOptions.RemoveEmptyEntries); } var types = BindingReflectionExtensions.SelfAndBaseTypes(sourceType); foreach (var type in types) { if (indexerArgs == null) { PropertyInfo property = type.GetPropertyEx(path, PropertyFlags); if (property != null) { return(new BindingMemberInfo(path, property, sourceType)); } } else { PropertyInfo candidate = null; int valueTypeCount = -1; foreach (var property in type.GetPropertiesEx(PropertyFlags)) { var indexParameters = property.GetIndexParameters(); if (indexParameters.Length != indexerArgs.Length) { continue; } try { int count = 0; for (int i = 0; i < indexParameters.Length; i++) { var arg = indexerArgs[i]; var paramType = indexParameters[i].ParameterType; if (arg.StartsWith("\"", StringComparison.Ordinal) && arg.EndsWith("\"", StringComparison.Ordinal)) { if (paramType != typeof(string)) { break; } } else { BindingServiceProvider.ValueConverter(Empty, paramType, arg); if (paramType.IsValueType()) { count++; } } } if (valueTypeCount < count) { candidate = property; valueTypeCount = count; } } catch { ; } } if (candidate != null) { return(new BindingMemberInfo(path, candidate, sourceType)); } if (type.IsArray && type.GetArrayRank() == indexerArgs.Length) { return(new BindingMemberInfo(path, type)); } } EventInfo @event = type.GetEventEx(path, EventFlags); if (@event != null) { return(new BindingMemberInfo(path, @event, null)); } FieldInfo field = type.GetFieldEx(path, FieldFlags); if (field != null) { return(new BindingMemberInfo(path, field, sourceType)); } } if (typeof(IDynamicObject).IsAssignableFrom(sourceType)) { return(new BindingMemberInfo(path, false)); } if (typeof(ExpandoObject).IsAssignableFrom(sourceType)) { return(new BindingMemberInfo(path, true)); } if (path.EndsWith(AttachedMemberConstants.ChangedEventPostfix, StringComparison.Ordinal)) { var memberName = path.Substring(0, path.Length - 7); var member = GetBindingMember(sourceType, memberName, false, false); if (member != null && member.CanObserve) { return(new BindingMemberInfo(path, null, member)); } } return(null); }