protected override LightDictionaryBase <string, object> GetOrAddAttachedDictionary(object item, bool addNew) { var model = item as NotifyPropertyChangedBase; if (model != null) { return(AttachedValueProviderDefault.GetOrAddAttachedValues(model, true)); } #if TOUCH var nsObject = item as NSObject; if (nsObject != null) { var handle = nsObject.Handle; if (handle == IntPtr.Zero) { if (addNew) { Tracer.Error("The object {0} is disposed the attached values cannot be obtained", item.GetType()); return(new AttachedValueDictionary()); } return(null); } AttachedValueHolder holder; lock (AttachedValueHolders) { if (!AttachedValueHolders.TryGetValue(handle, out holder)) { if (!addNew) { return(null); } holder = new AttachedValueHolder(nsObject); AttachedValueHolders[handle] = holder; } } return(holder.GetOrCreateDictionary()); } #elif !WINFORMS && !NET_STANDARD && !ANDROID && !TOUCH && !XAMARIN_FORMS //Synchronization is not necessary because accessing the DependencyObject is possible only from the main thread. var dependencyObject = item as DependencyObject; if (dependencyObject != null) { var dict = (AttachedValueDictionary)dependencyObject.GetValue(AttachedValueDictionaryProperty); if (dict == null && addNew) { dict = new AttachedValueDictionary(); dependencyObject.SetValue(AttachedValueDictionaryProperty, dict); } return(dict); } #elif XAMARIN_FORMS var bindableObject = item as BindableObject; if (bindableObject != null) { var dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty); if (dict == null && addNew) { lock (_internalDictionary) { dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty); if (dict == null) { dict = new AttachedValueDictionary(); bindableObject.SetValue(AttachedValueDictionaryProperty, dict); } } } return(dict); } #elif ANDROID if (SetTagSupported) { var view = item as View; if (view.IsAlive()) { var dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties); if (dict == null && addNew) { lock (_internalDictionary) { dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties); if (dict == null) { dict = new AttachedValueDictionaryJava(); view.SetTag(Resource.Id.AttachedProperties, dict); } } } return(dict?.Dictionary); } } //.NET object (Preference) is garbage collected and all attached members too but Java object is still alive. //Save values to activity dictionary. var pref = item as Preference; if (pref.IsAlive() && pref.HasKey) { try { var activityView = pref.Context as IActivityView; if (activityView != null) { var metadata = activityView.Mediator.Metadata; var key = pref.Key + pref.GetType().FullName + pref.GetHashCode(); object v; if (!metadata.TryGetValue(key, out v)) { if (addNew) { v = new AttachedValueDictionary(); metadata[key] = v; } } return((LightDictionaryBase <string, object>)v); } } catch { ; } } #endif if (addNew) { return(_internalDictionary.GetValue(item, CreateDictionaryDelegate)); } AttachedValueDictionary value; _internalDictionary.TryGetValue(item, out value); return(value); }
protected override bool ClearInternal(object item) { var model = item as NotifyPropertyChangedBase; if (model != null) { AttachedValueProviderDefault.ClearAttachedValues(model); return(true); } #if TOUCH var nsObject = item as NSObject; if (nsObject != null) { var handle = nsObject.Handle; if (handle == IntPtr.Zero) { return(false); } objc_setAssociatedObject(handle, AttachedValueKeyHandle, IntPtr.Zero, OBJC_ASSOCIATION_POLICY.OBJC_ASSOCIATION_RETAIN); AttachedValueHolder value; lock (AttachedValueHolders) { if (AttachedValueHolders.TryGetValue(handle, out value)) { AttachedValueHolders.Remove(handle); } } if (value == null) { return(false); } value.Dispose(); return(true); } #elif !WINFORMS && !NET_STANDARD && !ANDROID && !TOUCH && !XAMARIN_FORMS var dependencyObject = item as DependencyObject; if (dependencyObject != null) { dependencyObject.ClearValue(AttachedValueDictionaryProperty); return(true); } #elif XAMARIN_FORMS var bindableObject = item as BindableObject; if (bindableObject != null) { bindableObject.ClearValue(AttachedValueDictionaryProperty); return(true); } #elif ANDROID if (SetTagSupported) { var view = item as View; if (view.IsAlive()) { view.SetTag(Resource.Id.AttachedProperties, null); return(true); } } var pref = item as Preference; if (pref.IsAlive() && pref.HasKey) { try { var activityView = pref.Context as IActivityView; if (activityView != null) { var key = pref.Key + pref.GetType().FullName + pref.GetHashCode(); if (activityView.Mediator.Metadata.Remove(key)) { return(true); } } } catch { ; } } #endif return(_internalDictionary.Remove(item)); }