Esempio n. 1
0
        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;
                    }
                }
            }
        }
Esempio n. 2
0
        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;
        }