Exemplo n.º 1
0
 internal static void ValidateSources(DependencyObject d, DependencySource[] newSources, Expression expr)
 {
     // Make sure all Sources are owned by the same thread.
     if (newSources != null) 
     {
         Dispatcher dispatcher = d.Dispatcher; 
         for (int i = 0; i < newSources.Length; i++) 
         {
             Dispatcher sourceDispatcher = newSources[i].DependencyObject.Dispatcher; 
             if (sourceDispatcher != dispatcher && !(expr.SupportsUnboundSources && sourceDispatcher == null))
             {
                 throw new ArgumentException(SR.Get(SRID.SourcesMustBeInSameThread));
             } 
         }
     } 
 } 
Exemplo n.º 2
0
        internal static void UpdateSourceDependentLists(DependencyObject d, DependencyProperty dp, DependencySource[] sources, Expression expr, bool add) 
        {
            // Sources already validated to be on the same thread as Dependent (d)

            if (sources != null) 
            {
                // don't hold a reference on the dependent if the expression is doing 
                // the invalidations.  This helps avoid memory leaks (bug 871139) 
                if (expr.ForwardsInvalidations)
                { 
                    d = null;
                    dp = null;
                }
 
                for (int i = 0; i < sources.Length; i++)
                { 
                    DependencySource source = sources[i]; 

                    // A Sealed DependencyObject does not have a Dependents list 
                    // so don't bother updating it (or attempt to add one).

                    Debug.Assert((!source.DependencyObject.IsSealed) ||
                            (DependentListMapField.GetValue(source.DependencyObject) == default(object))); 

                    if (!source.DependencyObject.IsSealed) 
                    { 
                        // Retrieve the DependentListMap for this source
                        // The list of dependents to invalidate is stored using a special negative key 

                        FrugalMap dependentListMap;
                        object value = DependentListMapField.GetValue(source.DependencyObject);
                        if (value != null) 
                        {
                            dependentListMap = (FrugalMap)value; 
                        } 
                        else
                        { 
                            dependentListMap = new FrugalMap();
                        }

                        // Get list of DependentList off of ID map of Source 
                        object dependentListObj = dependentListMap[source.DependencyProperty.GlobalIndex];
                        Debug.Assert(dependentListObj != null, "dependentList should either be unset or non-null"); 
 
                        // Add/Remove new Dependent (this) to Source's list
                        if (add) 
                        {
                            DependentList dependentList;
                            if (dependentListObj == DependencyProperty.UnsetValue)
                            { 
                                dependentListMap[source.DependencyProperty.GlobalIndex] = dependentList = new DependentList();
                            } 
                            else 
                            {
                                dependentList = (DependentList)dependentListObj; 
                            }

                            dependentList.Add(d, dp, expr);
                        } 
                        else
                        { 
                            if (dependentListObj != DependencyProperty.UnsetValue) 
                            {
                                DependentList dependentList = (DependentList)dependentListObj; 

                                dependentList.Remove(d, dp, expr);

                                if (dependentList.IsEmpty) 
                                {
                                    // No more dependencies for this property; reclaim the space if we can. 
                                    dependentListMap[source.DependencyProperty.GlobalIndex] = DependencyProperty.UnsetValue; 
                                }
                            } 
                        }

                        // Set the updated struct back into the source's _localStore.
                        DependentListMapField.SetValue(source.DependencyObject, dependentListMap); 
                    }
                } 
            } 
        }
Exemplo n.º 3
0
        // 
        // Changes the sources of an existing Expression 
        //
        internal static void ChangeExpressionSources(Expression expr, DependencyObject d, DependencyProperty dp, DependencySource[] newSources) 
        {
            if (!expr.ForwardsInvalidations)
            {
                // Get current local value (should be provided Expression) 
                // (No need to go through read local callback, just checking
                // for presence of Expression) 
                EntryIndex entryIndex = d.LookupEntry(dp.GlobalIndex); 

                if (!entryIndex.Found || (d._effectiveValues[entryIndex.Index].LocalValue != expr)) 
                {
                    throw new ArgumentException(SR.Get(SRID.SourceChangeExpressionMismatch));
                }
            } 

            // Get current sources 
            // CALLBACK 
            DependencySource[] currentSources = expr.GetSources();
 
            // Remove old
            if (currentSources != null)
            {
                UpdateSourceDependentLists(d, dp, currentSources, expr, false);  // Remove 
            }
 
            // Add new 
            if (newSources != null)
            { 
                UpdateSourceDependentLists(d, dp, newSources, expr, true);  // Add
            }
        }
Exemplo n.º 4
0
        /// <summary>
        ///     List of sources of the Expression
        /// </summary> 
        /// <returns>Sources list</returns>
        internal override DependencySource[] GetSources() 
        { 
            int j, k;
            int n = (_sources != null) ? _sources.Length : 0; 
            if (n == 0)
                return null;

            DependencySource[] result = new DependencySource[n]; 

            // convert the weak references into strong ones 
            for (j=0, k=0; k<n; ++k) 
            {
                DependencyObject d = _sources[k].DependencyObject; 
                if (d != null)
                {
                    result[j++] = new DependencySource(d, _sources[k].DependencyProperty);
                } 
            }
 
            // if any of the references died, return a shortened list 
            if (j < n)
            { 
                DependencySource[] temp = result;
                result = new DependencySource[j];
                Array.Copy(temp, 0, result, 0, j);
            } 

            return result; 
        } 
Exemplo n.º 5
0
        // change WeakDependencySources to (strong) DependencySources, and notify 
        // the property engine about the new sources 
        void ChangeSources(DependencyObject target, DependencyProperty dp, WeakDependencySource[] newSources)
        { 
            DependencySource[] sources;

            if (newSources != null)
            { 
                // convert weak reference to strong
                sources = new DependencySource[newSources.Length]; 
                int n = 0; 
                for (int i = 0; i < newSources.Length; ++i)
                { 
                    DependencyObject sourceDO = newSources[i].DependencyObject;
                    if (sourceDO != null)
                    {
                        // only include sources that are still alive 
                        sources[n++] = new DependencySource(sourceDO, newSources[i].DependencyProperty);
                    } 
                } 

                // if any of the sources were no longer alive, trim the array 
                if (n < newSources.Length)
                {
                    DependencySource[] temp;
                    if (n > 0) 
                    {
                        temp = new DependencySource[n]; 
                        Array.Copy(sources, 0, temp, 0, n); 
                    }
                    else 
                    {
                        temp = null;
                    }
 
                    sources = temp;
                } 
            } 
            else
            { 
                sources = null;
            }

            // notify property engine 
            ChangeSources(target, dp, sources);
        } 
Exemplo n.º 6
0
        /// <summary> 
        ///     Dynamically change this Expression sources (availiable only for NonShareable
        ///     Expressions) 
        /// </summary>
        /// <remarks>
        ///     Expression must be in use on provided DependencyObject/DependencyProperty.
        ///     GetSources must reflect the old sources to be replaced by the provided newSources. 
        /// </remarks>
        /// <param name="d">DependencyObject whose sources are to be updated</param> 
        /// <param name="dp">The property that the Expression is set to</param> 
        /// <param name="newSources">New sources</param>
        internal void ChangeSources(DependencyObject d, DependencyProperty dp, DependencySource[] newSources) 
        {
            if (d == null && !ForwardsInvalidations)
            {
                throw new ArgumentNullException("d"); 
            }
 
            if (dp == null && !ForwardsInvalidations) 
            {
                throw new ArgumentNullException("dp"); 
            }

            if (Shareable)
            { 
                throw new InvalidOperationException(SR.Get(SRID.ShareableExpressionsCannotChangeSources));
            } 
 
            DependencyObject.ValidateSources(d, newSources, this);
 
            // Additional validation in callee
            if (ForwardsInvalidations)
            {
                DependencyObject.ChangeExpressionSources(this, null, null, newSources); 
            }
            else 
            { 
                DependencyObject.ChangeExpressionSources(this, d, dp, newSources);
            } 
        }