Пример #1
0
 public PathItem(EqualityWeakReference source, int index, Delegate onchanged)
 {
     Source    = source;
     Index     = index;
     OnChanged = onchanged;
     IsArray   = false;
 }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="rootSource"></param>
        /// <param name="fullpath"></param>
        /// <param name="factory">what to do when an intermediate property changed</param>
        /// <param name="OnfinalBind"></param>
        public void Bind(object rootSource, string fullpath, OnChangeDelegateFactoryDelegate factory, OnBindLastItem OnfinalBind)
        {
            _Items        = new List <PathItem>();
            _PropertyPath = fullpath;
            _Source       = new EqualityWeakReference(rootSource);
            List <string> pahtitems = new List <string>(fullpath.Split('.'));
            int           i         = -1;

            while (++i < pahtitems.Count)
            {
                string pathitem = pahtitems[i];
                if (pathitem.EndsWith("]"))
                {
                    pathitem = pathitem.TrimEnd(']');
                    PathItem p = new PathItem(pathitem.Substring(0, pathitem.IndexOf('[')));
                    p.Index = i;
                    _Items.Add(p);
                    string arrayIndex = pathitem.Substring(pathitem.IndexOf('[') + 1);
                    p.IsArray    = true;
                    p.ArrayIndex = int.Parse(arrayIndex);
                }
                else
                {
                    PathItem p = new PathItem(pathitem);
                    p.Index = i;
                    _Items.Add(p);
                }
            }
            _OnfinalBind = OnfinalBind;
            _factory     = factory;
            BindPropertyPath(rootSource, 0);
        }
Пример #3
0
 public void Fire(EqualityWeakReference weak)
 {
     if (weak.IsAlive && _BindingEnabled)
     {
         if (_HasCalled)
         {
             throw new Exception(string.Format("The current binding has recursion =>{0}('{1}')", weak.Target.GetType().FullName, PropertyName));
         }
         _HasCalled = true;
         try
         {
             if (_ApplyBindingContext != null)
             {
                 _ApplyBindingContext.Send(DoNotifyValueChanged, weak.Target);
             }
             else
             {
                 DoNotifyValueChanged(weak.Target);
             }
         }
         finally
         {
             _HasCalled = false;
         }
     }
 }
Пример #4
0
 public PathItem(EqualityWeakReference source, int index, Delegate onchanged, bool isArray, int arrayIndex)
 {
     Source     = source;
     Index      = index;
     OnChanged  = onchanged;
     IsArray    = isArray;
     ArrayIndex = arrayIndex;
 }
Пример #5
0
        internal static void RemoveNotify(object source, string propName, Delegate del)
        {
            INotifyPropertyChanged inotify = source as INotifyPropertyChanged;

            if (inotify != null)
            {
                EqualityWeakReference weak = new EqualityWeakReference(inotify);
                //le but est ici de ne s'abonner qu'une fois
                Dictionary <string, IOneNotify> dico = null;
                if (_SourceChanged.TryGetValue(weak, out dico))
                {
                    if (dico.ContainsKey(propName))
                    {
                        dico[propName].OnChanged = Delegate.Remove(dico[propName].OnChanged, del);
                        if (dico[propName].OnChanged == null)
                        {
                            dico.Remove(propName);
                        }
                    }
                }
            }
            else if (source != null)
            {
                //try with old mode "PropertyName"Changed event
                string    eventName = string.Format("{0}Changed", propName);
                EventInfo evInfo    = source.GetType().GetEvent(eventName);
                if (evInfo != null)
                {
                    EqualityWeakReference weak = new EqualityWeakReference(source);
                    //le but est ici de ne s'abonner qu'une fois
                    Dictionary <string, IOneNotify> dico = null;
                    if (_SourceChanged.TryGetValue(weak, out dico))
                    {
                        if (dico.ContainsKey(propName))
                        {
                            dico[propName].OnChanged = Delegate.Remove(dico[propName].OnChanged, del);
                            if (dico[propName].OnChanged == null)
                            {
                                evInfo.RemoveEventHandler(source, dico[propName].PropertyChangedEvent);
                                dico.Remove(propName);
                            }
                        }
                    }
                }
            }
        }
Пример #6
0
        public override bool Equals(object o)
        {
            if (o == null)
            {
                return(false);
            }
            if (o.GetHashCode() != this._hashCode)
            {
                return(false);
            }
            EqualityWeakReference other = o as EqualityWeakReference;

            if ((o != this) && (!this.IsAlive || !object.ReferenceEquals(other.Target, this.Target)))
            {
                return(false);
            }
            return(true);
        }
Пример #7
0
        internal static IOneNotify GetOneNotify(object source, string propName)
        {
            INotifyPropertyChanged inotify = source as INotifyPropertyChanged;

            if (inotify != null)
            {
                EqualityWeakReference weak = new EqualityWeakReference(inotify);
                //le but est ici de ne s'abonner qu'une fois
                Dictionary <string, IOneNotify> dico = null;
                if (_SourceChanged.TryGetValue(weak, out dico))
                {
                    IOneNotify result = null;
                    dico.TryGetValue(propName, out result);
                    return(result);
                }
            }
            return(null);
        }
Пример #8
0
        /// <summary>
        /// gestion de la notification sur INotifyPropertyChanged
        /// </summary>
        /// <typeparam name="T">type de la propriété observée</typeparam>
        /// <param name="source">source</param>
        /// <param name="propName">property à observer</param>
        /// <param name="gethandler">"get" a appeler a chaque changements</param>
        /// <param name="OnValueChange">la déléguée à appelée après chaque changed de la source</param>
        internal static void AddNotify <T>(object source, string propName, GetHandlerDelegate <T> gethandler, OnChangeDelegate <T> OnValueChange, SynchronizationContext applyBindingContext)
        {
            INotifyPropertyChanged inotify = source as INotifyPropertyChanged;

            if (inotify != null)
            {
                EqualityWeakReference weak = new EqualityWeakReference(inotify);
                //le but est ici de ne s'abonner qu'une fois
                Dictionary <string, IOneNotify> dico = null;
                if (!_SourceChanged.TryGetValue(weak, out dico))
                {
                    dico = new Dictionary <string, IOneNotify>();
                    _SourceChanged.Add(weak, dico);
                    inotify.PropertyChanged += delegate(object sender, PropertyChangedEventArgs e)
                    {
                        //je minimise le nombre de get, en founissant la valeur qui à changé
                        if (dico.ContainsKey(e.PropertyName))
                        {
                            dico[e.PropertyName].Fire(weak);
                        }
                    };
                }
                ///plusieurs abonnement si nécessaire pour une propriété binding de 1 prop vers plusieurs dest
                OneNotify <T> binding = null;
                if (dico.ContainsKey(propName))
                {
                    binding            = (OneNotify <T>)dico[propName];
                    binding._OnChanged = (OnChangeDelegate <T>)Delegate.Combine(binding._OnChanged, OnValueChange);
                }
                else
                {
                    binding = new OneNotify <T>(gethandler, OnValueChange);
                    binding._ApplyBindingContext = applyBindingContext;
                    binding.PropertyName         = propName;
                    dico[propName] = binding;
                }
            }
            else if (source != null)
            {
                //try with old mode "PropertyName"Changed event
                string    eventName = string.Format("{0}Changed", propName);
                EventInfo evInfo    = source.GetType().GetEvent(eventName);
                if (evInfo != null)
                {
                    EqualityWeakReference weak = new EqualityWeakReference(source);
                    //le but est ici de ne s'abonner qu'une fois
                    Dictionary <string, IOneNotify> dico = null;
                    if (!_SourceChanged.TryGetValue(weak, out dico))
                    {
                        dico = new Dictionary <string, IOneNotify>();
                        _SourceChanged.Add(weak, dico);
                    }

                    ///plusieurs abonnement si nécessaire pour une propriété binding de 1 prop vers plusieurs dest
                    OneNotify <T> binding = null;
                    if (dico.ContainsKey(propName))
                    {
                        binding            = (OneNotify <T>)dico[propName];
                        binding._OnChanged = (OnChangeDelegate <T>)Delegate.Combine(binding._OnChanged, OnValueChange);
                    }
                    else
                    {
                        binding = new OneNotify <T>(gethandler, OnValueChange);
                        binding.PropertyName          = propName;
                        binding._ApplyBindingContext  = applyBindingContext;
                        binding._PropertyChangedEvent = delegate
                        {
                            binding.Fire(weak);
                        };
                        dico[propName] = binding;
                        evInfo.AddEventHandler(source, binding._PropertyChangedEvent);
                    }
                }
            }
        }
Пример #9
0
        private object BindToArray(object source, int currentIndex, PathItem pathitem)
        {
            //in future use, it will be insterresting to keep arrayIndex as string (i.e dictionary)
            int intArrayIndex = pathitem.ArrayIndex;

            EqualityWeakReference weakSource;

#if !SILVERLIGHT
            //Here source is a list, bindinglist, ... or has simply indexer
            if (source is IBindingList)
            {
                BindingListNotificationWrapper wrapper = new BindingListNotificationWrapper((IBindingList)source);
                wrapper.SetIndex(intArrayIndex);
                weakSource = new EqualityWeakReference(source);
                wrapper.CollectionChanged += delegate(object sender, CollectionChangedEventArgs e)
                {
                    if (weakSource.IsAlive)
                    {
                        UnBindReBindListItem(currentIndex, intArrayIndex, weakSource.Target);
                    }
                };
                IList l = ((IList)source);
                if (l.Count > intArrayIndex)
                {
                    source = l[intArrayIndex];
                }
                else
                {
                    source = null;
                }
                pathitem.ArrayWrapper = wrapper;
            }
            else
#endif
            if (source is ICollectionChanged)
            {
                weakSource = new EqualityWeakReference(source);
                ((ICollectionChanged)source).CollectionChanged += delegate(object sender, CollectionChangedEventArgs e)
                {
                    if (weakSource.IsAlive)
                    {
                        if (e.Action == CollectionChangedAction.Reset || e.NewIndex == intArrayIndex || e.OldIndex == intArrayIndex)
                        {
                            UnBindReBindListItem(currentIndex, intArrayIndex, weakSource.Target);
                        }
                    }
                };
                if (((IList)source).Count > intArrayIndex)
                {
                    source = ((IList)source)[intArrayIndex];
                }
                else
                {
                    source = null;
                }
            }
            else
            {
                IList l = source as IList;
                if (l != null)
                {
                    source = ((IList)source)[intArrayIndex];
                }
                else
                {
                    source = null;
                }
            }
            return(source);
        }
Пример #10
0
        public void BindPropertyPath(object source, int index)
        {
            if (source == null)
            {
                return;
            }
            PathItem pathitem = _Items[index];
            bool     isArray  = pathitem.IsArray;

            PropertyInfo pi = source.GetType().GetProperty(pathitem.PropertyName);

            if (pi == null)
            {
                CheckPropertyInfo(true, _PropertyPath, pathitem.PropertyName, source.GetType());
            }
            if (index == _Items.Count - 1)
            {
                pathitem.Source = new EqualityWeakReference(source);
                if (_OnfinalBind != null)
                {
                    _OnfinalBind(index, pi, source);
                }
                pathitem.IsBind = true;
                if (pathitem.IsArray && _factory != null)
                {
                    OnChangeDelegate <object> onchanged = delegate(object value)
                    {
                        if (pathitem.Source.IsAlive)
                        {
                            object target = pathitem.Source.Target;
                            RemoveNotify(index);
                            BindPropertyPath(target, index);
                        }
                    };
                    pathitem.OnChanged = onchanged;
                    //Add notification on source changed
                    AddNotify(source, pathitem.PropertyName, onchanged);
                }
            }
            else
            {
                EqualityWeakReference weakSource = new EqualityWeakReference(source);
                int currentIndex = index + 1;

                OnChangeDelegate <object> onchanged = null;
                if (_factory != null)
                {
                    onchanged = _factory(currentIndex, weakSource);
                }
                pathitem.Source    = weakSource;
                pathitem.OnChanged = onchanged;
                pathitem.IsBind    = true;
                //Add notification on source changed
                AddNotify(source, pathitem.PropertyName, onchanged);
                source = pi.GetValue(source, null);
                if (isArray)
                {
                    source = BindToArray(source, currentIndex, pathitem);
                }
                BindPropertyPath(source, currentIndex);
            }
        }