コード例 #1
0
 /// <summary>
 /// Fire the event.
 /// </summary>
 /// <param name="sender">The markup extension that reached an enpoint.</param>
 /// <param name="args">The event args containing the endpoint information.</param>
 internal static void Invoke(NestedMarkupExtension sender, EndpointReachedEventArgs args)
 {
     lock (listenersLock)
     {
         foreach (var wr in listeners.ToList())
         {
             var targetReference = wr.Target;
             if (targetReference != null)
             {
                 ((NestedMarkupExtension)targetReference).OnEndpointReached(sender, args);
             }
             else
             {
                 listeners.Remove(wr);
             }
         }
     }
 }
コード例 #2
0
        /// <summary>
        /// An event handler that is called from the static <see cref="EndpointReachedEvent"/> class.
        /// </summary>
        /// <param name="sender">The markup extension that reached an enpoint.</param>
        /// <param name="args">The event args containing the endpoint information.</param>
        private void OnEndpointReached(NestedMarkupExtension sender, EndpointReachedEventArgs args)
        {
            if (args.Handled)
            {
                return;
            }

            var path = GetPathToEndpoint(args.Endpoint);

            if (path == null)
            {
                return;
            }

            if ((this != sender) && !UpdateOnEndpoint(path.EndPoint))
            {
                return;
            }

            args.EndpointValue = UpdateNewValue(path);
            args.Handled       = true;
        }
コード例 #3
0
            /// <summary>
            /// Fire the event.
            /// </summary>
            /// <param name="rootObjectHashCode"><paramref name="sender"/>s root object hash code.</param>
            /// <param name="sender">The markup extension that reached an end point.</param>
            /// <param name="args">The event args containing the endpoint information.</param>
            internal static void Invoke(int rootObjectHashCode, NestedMarkupExtension sender, EndpointReachedEventArgs args)
            {
                lock (listenersLock)
                {
                    // Do nothing if we don't have this root object hash.
                    if (!listeners.ContainsKey(rootObjectHashCode))
                    {
                        return;
                    }

                    foreach (var wr in listeners[rootObjectHashCode].ToList())
                    {
                        var targetReference = wr.Target;
                        if (targetReference is NestedMarkupExtension)
                        {
                            ((NestedMarkupExtension)targetReference).OnEndpointReached(sender, args);
                        }
                        else
                        {
                            listeners[rootObjectHashCode].Remove(wr);
                        }
                    }
                }
            }
コード例 #4
0
        /// <summary>
        /// The ProvideValue method of the <see cref="MarkupExtension"/> base class.
        /// </summary>
        /// <param name="serviceProvider">A service provider.</param>
        /// <returns>The value of the extension, or this if something gone wrong (needed for Templates).</returns>
        public sealed override object ProvideValue(IServiceProvider serviceProvider)
        {
            // If the service provider is null, return this
            if (serviceProvider == null)
            {
                return(this);
            }

            OnServiceProviderChanged(serviceProvider);

            // Try to cast the passed serviceProvider to a IProvideValueTarget
            IProvideValueTarget service = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;

            // If the cast fails, return this
            if (service == null)
            {
                return(this);
            }

#if NET35
            rootObjectHashCode = 0;
#else
            // Try to cast the passed serviceProvider to a IRootObjectProvider and if the cast fails return null
            IRootObjectProvider rootObject = serviceProvider.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
            if (rootObject == null)
            {
                rootObjectHashCode = 0;
            }
            else
            {
                rootObjectHashCode = rootObject.RootObject.GetHashCode();

                // We only sign up once to the Window Closed event to clear the listeners list of root object.
                if (rootObject.RootObject != null && !EndpointReachedEvent.ContainsRootObjectHash(rootObjectHashCode))
                {
                    if (rootObject.RootObject is Window window)
                    {
                        window.Closed += delegate(object sender, EventArgs args) { EndpointReachedEvent.ClearListenersForRootObject(rootObjectHashCode); };
                    }
                    else if (rootObject.RootObject is FrameworkElement frameworkElement)
                    {
                        void frameworkElementUnloadedHandler(object sender, RoutedEventArgs args)
                        {
                            frameworkElement.Unloaded -= frameworkElementUnloadedHandler;
                            EndpointReachedEvent.ClearListenersForRootObject(rootObjectHashCode);
                        }

                        frameworkElement.Unloaded += frameworkElementUnloadedHandler;
                    }
                }
            }
#endif

            // Declare a target object and property
            TargetInfo endPoint            = null;
            object     targetObject        = service.TargetObject;
            object     targetProperty      = service.TargetProperty;
            int        targetPropertyIndex = -1;
            Type       targetPropertyType  = null;

            // First, check if the service provider is of type SimpleProvideValueServiceProvider
            //      -> If yes, get the target property type and index.
            // Check if the service.TargetProperty is a DependencyProperty or a PropertyInfo and set the type info
            if (serviceProvider is SimpleProvideValueServiceProvider)
            {
                targetPropertyType  = ((SimpleProvideValueServiceProvider)serviceProvider).TargetPropertyType;
                targetPropertyIndex = ((SimpleProvideValueServiceProvider)serviceProvider).TargetPropertyIndex;
                endPoint            = ((SimpleProvideValueServiceProvider)serviceProvider).EndPoint;
            }
            else
            {
                if (targetProperty is PropertyInfo)
                {
                    PropertyInfo pi = (PropertyInfo)targetProperty;
                    targetPropertyType = pi.PropertyType;

                    // Kick out indexers.
                    if (pi.GetIndexParameters().Any())
                    {
                        throw new InvalidOperationException("Indexers are not supported!");
                    }
                }
                else if (targetProperty is DependencyProperty)
                {
                    DependencyProperty dp = (DependencyProperty)targetProperty;
                    targetPropertyType = dp.PropertyType;
                }
                else
                {
                    return(this);
                }
            }

            // If the service.TargetObject is System.Windows.SharedDp (= not a DependencyObject and not a PropertyInfo), we return "this".
            // The SharedDp will call this instance later again.
            if (!(targetObject is DependencyObject) && !(targetProperty is PropertyInfo))
            {
                return(this);
            }

            // If the target object is a DictionaryEntry we presumably are facing a resource scenario.
            // We will be called again later with the proper target.
            if (targetObject is DictionaryEntry)
            {
                return(null);
            }

            // Search for the target in the target object list
            WeakReference wr = (from kvp in targetObjects
                                where kvp.Key.Target == targetObject
                                select kvp.Key).FirstOrDefault();

            if (wr == null)
            {
                // If it's the first object, call the appropriate action
                if (targetObjects.Count == 0)
                {
                    if (OnFirstTarget != null)
                    {
                        OnFirstTarget();
                    }
                }

                // Add the target as a WeakReference to the target object list
                wr = new WeakReference(targetObject);
                targetObjects.Add(wr, new Dictionary <Tuple <object, int>, Type>());

                // Add this extension to the ObjectDependencyManager to ensure the lifetime along with the target object
                ObjectDependencyManager.AddObjectDependency(wr, this);
            }

            // Finally, add the target prop and info to the list of this WeakReference
            Tuple <object, int> tuple = new Tuple <object, int>(targetProperty, targetPropertyIndex);
            if (!targetObjects[wr].ContainsKey(tuple))
            {
                targetObjects[wr].Add(tuple, targetPropertyType);
            }

            // Sign up to the EndpointReachedEvent only if the markup extension wants to do so.
            EndpointReachedEvent.AddListener(rootObjectHashCode, this);

            // Create the target info
            TargetInfo info = new TargetInfo(targetObject, targetProperty, targetPropertyType, targetPropertyIndex);

            // Return the result of FormatOutput
            object result = null;

            if (info.IsEndpoint)
            {
                var args = new EndpointReachedEventArgs(info);
                EndpointReachedEvent.Invoke(rootObjectHashCode, this, args);
                result = args.EndpointValue;
            }
            else
            {
                result = FormatOutput(endPoint, info);
            }

            // Check type
            if (typeof(IList).IsAssignableFrom(targetPropertyType))
            {
                return(result);
            }
            else if ((result != null) && targetPropertyType.IsAssignableFrom(result.GetType()))
            {
                return(result);
            }

            // Finally, if nothing was there, return null or default
            if (targetPropertyType.IsValueType)
            {
                return(Activator.CreateInstance(targetPropertyType));
            }
            else
            {
                return(null);
            }
        }