public PathItem(EqualityWeakReference source, int index, Delegate onchanged) { Source = source; Index = index; OnChanged = onchanged; IsArray = false; }
/// <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); }
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; } } }
public PathItem(EqualityWeakReference source, int index, Delegate onchanged, bool isArray, int arrayIndex) { Source = source; Index = index; OnChanged = onchanged; IsArray = isArray; ArrayIndex = arrayIndex; }
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); } } } } } }
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); }
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); }
/// <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); } } } }
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); }
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); } }