コード例 #1
0
        /// <summary> Implements the functionality documented in the other overloads. </summary>
        private static void Bind(INotifyPropertyChanged source, string propertyName, string propertyOnPropertyName, PropertyChangedEventHandler handler, object defaultValue, Type propertyOnPropertyType)
        {
            Contract.Requires(source != null);
            Contract.Requires(handler != null);
            Contract.Requires(source.GetType().GetProperty(propertyName) != null);
            var sourceProperty     = GetProperty(source.GetType(), propertyName);
            var sourcePropertyType = GetPropertyType(source.GetType(), propertyName);

            Contract.Requires(sourcePropertyType.Implements(typeof(INotifyPropertyChanged)), $"The property on the source must implement '{nameof(INotifyPropertyChanged)}'");
            Contract.Requires(GetPropertyType(sourcePropertyType, propertyOnPropertyName) != null, $"Property '{propertyName}' was not found on type '{sourcePropertyType.Name}'");
            Contract.Requires(propertyOnPropertyType.IsAssignableFrom(GetPropertyType(sourcePropertyType, propertyOnPropertyName)));
            Contract.Requires(propertyOnPropertyType.IsInstanceOfType(defaultValue) || (ReferenceEquals(defaultValue, null) && !propertyOnPropertyType.IsValueType));

            handler = handler.FilterOn(propertyOnPropertyName);
            PropertyChangedEventHandler onSourcePropertyChanged = (sender, eventArg) =>
            {
                Contract.Requires(eventArg is IPropertyMutatedEventArgs);

                var e = (IPropertyMutatedEventArgs)eventArg;

                var oldSource = (INotifyPropertyChanged)e.OldValue;
                if (oldSource != null)
                {
                    oldSource.PropertyChanged -= handler;
                }

                var newSource = (INotifyPropertyChanged)e.NewValue;
                if (newSource != null)
                {
                    newSource.PropertyChanged += handler;
                }

                var oldValue = GetPropertyValue(oldSource, propertyOnPropertyName, defaultValue: defaultValue);
                var newValue = GetPropertyValue(newSource, propertyOnPropertyName, defaultValue: defaultValue);
                if (!Equals(oldValue, newValue))                 // uses virtual method oldValue.Equals(object)
                {
                    handler(newSource ?? oldSource, PropertyMutatedEventArgsExtensions.Create(propertyOnPropertyName, propertyOnPropertyType, oldValue, newValue));
                }
            };

            source.PropertyChanged += onSourcePropertyChanged.FilterOn(propertyName);

            object currentValue = sourceProperty.GetValue(source);

            // onSourcePropertyChanged is invoked regardless of whether currentValue equals sourcePropertyType.GetDefault()
            // because it hooks the handler onto currentValue.PropertyChange
            onSourcePropertyChanged(source, PropertyMutatedEventArgsExtensions.Create(propertyName, sourcePropertyType, sourcePropertyType.GetDefault(), currentValue));
        }