private void OnTargetMidPropertyChanged(object sender, PropertyChangedEventArgs e) { if (context != null && SynchronizationContext.Current != context) { context.Post((o) => { SynchronizationContext.SetSynchronizationContext(context); OnTargetMidPropertyChanged(sender, e); }, this); return; } for (int i = targetInfos.Length - 1; i >= 0; i--) { var info = targetInfos[i]; if (info.Name == e.PropertyName) { break; } var notify = targetObjects[i].Target as INotifyPropertyChanged; if (notify != null) { RemoveTargetHandlers(notify); } targetObjects[i] = null; } bool above = true; var tokens = TargetPath.Split('.'); for (int i = 0; i < targetInfos.Length; i++) { var info = targetInfos[i]; if (info.Name != e.PropertyName && above) { continue; } above = false; object targetObj = targetObjects[i].Target; if (targetObj == null) { Deactivate(); return; } if (targetObj.GetType().IsArray) { targetObj = ((Array)targetObj).GetValue(targetIndices[i].Cast <int>().ToArray()); } else { targetObj = info.GetValue(targetObj, targetIndices[i]); } targetObj = GetNotifier(targetObj); if (Device.Reflector.GetProperty(targetObj.GetType(), info.Name) == null) { var pairable = targetObj as IPairable; if (pairable != null) { targetObj = pairable.Pair; } } targetObjects[i + 1] = new WeakReference(targetObj); if (i >= targetInfos.Length - 2) { var notify = targetObj as INotifyPropertyChanged; if (notify != null) { RemoveTargetHandlers(notify); notify.PropertyChanged += OnTargetEndPropertyChanged; } OnTargetEndPropertyChanged(this, new PropertyChangedEventArgs(targetInfos.Last().Name)); break; } else { var notify = targetObj as INotifyPropertyChanged; if (notify != null) { RemoveTargetHandlers(notify); notify.PropertyChanged += OnTargetMidPropertyChanged; } } } }
internal void Activate() { var sourceObject = GetNotifier(Source ?? Target); var type = sourceObject.GetType(); var sourceTokens = SourcePath.Split('.'); sourceInfos = new PropertyInfo[sourceTokens.Length]; sourceObjects = new object[sourceTokens.Length]; sourceIndices = new object[sourceTokens.Length][]; for (int i = 0; i < sourceTokens.Length; i++) { string token = sourceTokens[i]; if (token[token.Length - 1] == ']') { int start = token.IndexOf('[') + 1; sourceIndices[i] = ParseIndex(token.Substring(start, token.Length - start - 1)); token = token.Substring(0, start - 1); } var props = Device.Reflector.GetProperties(type).Where(p => p.Name == token); var sourceInfo = props.FirstOrDefault(p => p.DeclaringType == type) ?? props.FirstOrDefault(); if (sourceInfo != null && sourceIndices[i] != null) { sourceObject = sourceInfo.GetValue(sourceObject, null); type = sourceObject.GetType(); if (!type.IsArray) { sourceInfo = Device.Reflector.GetProperty(type, "Item"); } } if (sourceInfo == null) { var pairable = sourceObject as IPairable; if (pairable != null && pairable.Pair != null) { sourceObject = pairable.Pair; type = sourceObject.GetType(); props = Device.Reflector.GetProperties(type).Where(p => p.Name == token); sourceInfo = props.FirstOrDefault(p => p.DeclaringType == type) ?? props.FirstOrDefault(); if (sourceInfo != null && sourceIndices[i] != null) { sourceObject = sourceInfo.GetValue(sourceObject, null); type = sourceObject.GetType(); if (!type.IsArray) { sourceInfo = Device.Reflector.GetProperty(type, "Item"); } } } } if (sourceInfo == null) { throw new ArgumentException(string.Format("Could not find a property with the name '{0}'.", token)); } if (i < sourceTokens.Length - 1) { var notify = sourceObject as INotifyPropertyChanged; if (notify != null) { RemoveSourceHandlers(notify); notify.PropertyChanged += OnSourceMidPropertyChanged; } } sourceInfos[i] = sourceInfo; sourceObjects[i] = sourceObject; if (type.IsArray) { type = sourceObject.GetType().GetElementType(); sourceObject = ((Array)sourceObject).GetValue(sourceIndices[i].Cast <int>().ToArray()); } else { type = sourceInfo.PropertyType; sourceObject = sourceInfo.GetValue(sourceObject, sourceIndices[i]); } sourceObject = GetNotifier(sourceObject); if (sourceObject != null) { type = sourceObject.GetType(); } } var notifier = sourceObjects.Last() as INotifyPropertyChanged; if (notifier != null) { RemoveSourceHandlers(notifier); notifier.PropertyChanged += OnSourceEndPropertyChanged; } var targetObject = GetNotifier(Target); type = targetObject.GetType(); var targetTokens = TargetPath.Split('.'); targetInfos = new PropertyInfo[targetTokens.Length]; targetObjects = new WeakReference[targetTokens.Length]; targetIndices = new object[targetTokens.Length][]; for (int i = 0; i < targetTokens.Length; i++) { string token = targetTokens[i]; if (token[token.Length - 1] == ']') { int start = token.IndexOf('[') + 1; targetIndices[i] = ParseIndex(token.Substring(start, token.Length - start - 1)); token = token.Substring(0, start - 1); } var props = Device.Reflector.GetProperties(type).Where(p => p.Name == token); var targetInfo = props.FirstOrDefault(p => p.DeclaringType == type) ?? props.FirstOrDefault(); if (targetInfo != null && targetIndices[i] != null) { targetObject = targetInfo.GetValue(targetObject, null); type = targetObject.GetType(); if (!type.IsArray) { targetInfo = Device.Reflector.GetProperty(type, "Item"); } } if (targetInfo == null) { var pairable = targetObject as IPairable; if (pairable != null && pairable.Pair != null) { targetObject = pairable.Pair; type = targetObject.GetType(); props = Device.Reflector.GetProperties(type).Where(p => p.Name == token); targetInfo = props.FirstOrDefault(p => p.DeclaringType == type) ?? props.FirstOrDefault(); if (targetInfo != null && targetIndices[i] != null) { targetObject = targetInfo.GetValue(targetObject, null); type = targetObject.GetType(); if (!type.IsArray) { targetInfo = Device.Reflector.GetProperty(type, "Item"); } } } } if (targetInfo == null) { throw new ArgumentException(string.Format("Could not find a property with the name '{0}'.", token)); } if (i < targetTokens.Length - 1) { var notify = targetObject as INotifyPropertyChanged; if (notify != null) { RemoveTargetHandlers(notify); notify.PropertyChanged += OnTargetMidPropertyChanged; } } targetInfos[i] = targetInfo; targetObjects[i] = new WeakReference(targetObject); if (type.IsArray) { type = targetObject.GetType().GetElementType(); targetObject = ((Array)targetObject).GetValue(targetIndices[i].Cast <int>().ToArray()); } else { type = targetInfo.PropertyType; targetObject = targetInfo.GetValue(targetObject, targetIndices[i]); } targetObject = GetNotifier(targetObject); if (targetObject != null) { type = targetObject.GetType(); } } notifier = targetObjects.Last().Target as INotifyPropertyChanged; if (notifier != null) { RemoveTargetHandlers(notifier); notifier.PropertyChanged += OnTargetEndPropertyChanged; } if (Mode == BindingMode.OneWayToSource) { OnTargetEndPropertyChanged(this, new PropertyChangedEventArgs(targetInfos.Last().Name)); } else { OnSourceEndPropertyChanged(this, new PropertyChangedEventArgs(sourceInfos.Last().Name)); } isActive = true; }