コード例 #1
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); 
                    }
                } 
            } 
        }
コード例 #2
0
 /// <summary> 
 ///     Constructor for EventHandlersStore
 /// </summary>
 public EventHandlersStore()
 { 
     _entries = new FrugalMap();
 } 
コード例 #3
0
        // Called during Style/Template Seal when encountering a property trigger that
        //  has associated TriggerActions.
        internal static void AddPropertyTriggerWithAction(TriggerBase triggerBase,
            DependencyProperty property, ref FrugalMap triggersWithActions)
        {
            object existing = triggersWithActions[property.GlobalIndex];

            if( existing == DependencyProperty.UnsetValue )
            {
                // No existing trigger, we put given trigger as entry.
                triggersWithActions[property.GlobalIndex] = triggerBase;
            }
            else
            {
                TriggerBase existingTriggerBase = existing as TriggerBase;
                if( existingTriggerBase != null )
                {
                    List<TriggerBase> newList = new List<TriggerBase>();

                    newList.Add(existingTriggerBase);
                    newList.Add(triggerBase);

                    triggersWithActions[property.GlobalIndex] = newList;
                }
                else
                {
                    Debug.Assert( existing is List<TriggerBase>,
                        "FrugalMap for holding List<TriggerBase> is holding an instance of unexpected type " + existing.GetType() );

                    List<TriggerBase> existingList = (List<TriggerBase>)existing;

                    existingList.Add(triggerBase);
                }
            }

            // Note the order in which we processed this trigger.
            triggerBase.EstablishLayer();
        }
コード例 #4
0
        //
        //  This method
        //  1. Adds shared table entries for property values set via Triggers
        //
        private static void ProcessTemplateTriggers(
            TriggerCollection                                           triggers,
            FrameworkTemplate                                           frameworkTemplate,
            ref FrugalStructList<ChildRecord>                           childRecordFromChildIndex,
            ref FrugalStructList<ItemStructMap<TriggerSourceRecord>>    triggerSourceRecordFromChildIndex,
            ref FrugalStructList<ContainerDependent>                    containerDependents,
            ref FrugalStructList<ChildPropertyDependent>                resourceDependents,
            ref ItemStructList<ChildEventDependent>                     eventDependents,
            ref HybridDictionary                                        dataTriggerRecordFromBinding,
            HybridDictionary                                            childIndexFromChildID,
            ref bool                                                    hasInstanceValues,
            ref HybridDictionary                                        triggerActions,
            FrameworkElementFactory                                     templateRoot,
            ref EventHandlersStore                                      eventHandlersStore,
            ref FrugalMap                                               propertyTriggersWithActions,
            ref HybridDictionary                                        dataTriggersWithActions,
            ref bool                                                    hasLoadedChangeHandler)
        {
            if (triggers != null)
            {
                int triggerCount = triggers.Count;
                for (int i = 0; i < triggerCount; i++)
                {
                    TriggerBase triggerBase = triggers[i];

                    Trigger trigger;
                    MultiTrigger multiTrigger;
                    DataTrigger dataTrigger;
                    MultiDataTrigger multiDataTrigger;
                    EventTrigger eventTrigger;

                    DetermineTriggerType( triggerBase, out trigger, out multiTrigger, out dataTrigger, out multiDataTrigger, out eventTrigger );

                    if ( trigger != null || multiTrigger != null||
                        dataTrigger != null || multiDataTrigger != null )
                    {
                        // Update the SourceChildIndex for each of the conditions for this trigger
                        TriggerCondition[] conditions = triggerBase.TriggerConditions;
                        for (int k=0; k<conditions.Length; k++)
                        {
                            conditions[k].SourceChildIndex = StyleHelper.QueryChildIndexFromChildName(conditions[k].SourceName, childIndexFromChildID);
                        }

                        // Set things up to handle Setter values
                        for (int j = 0; j < triggerBase.PropertyValues.Count; j++)
                        {
                            PropertyValue propertyValue = triggerBase.PropertyValues[j];

                            // Check for trigger rules that act on template children
                            if (propertyValue.ChildName == StyleHelper.SelfName)
                            {
                                // "Self" (container) trigger

                                // Track properties on the container that are being driven by
                                // the Template so that they can be invalidated during Template changes
                                StyleHelper.AddContainerDependent(propertyValue.Property, true /*fromVisualTrigger*/, ref containerDependents);
                            }

                            StyleHelper.UpdateTables(ref propertyValue, ref childRecordFromChildIndex,
                                ref triggerSourceRecordFromChildIndex, ref resourceDependents, ref dataTriggerRecordFromBinding,
                                childIndexFromChildID, ref hasInstanceValues);
                        }

                        // Set things up to handle TriggerActions
                        if( triggerBase.HasEnterActions || triggerBase.HasExitActions )
                        {
                            if( trigger != null )
                            {
                                StyleHelper.AddPropertyTriggerWithAction( triggerBase, trigger.Property, ref propertyTriggersWithActions );
                            }
                            else if( multiTrigger != null )
                            {
                                for( int k = 0; k < multiTrigger.Conditions.Count; k++ )
                                {
                                    Condition triggerCondition = multiTrigger.Conditions[k];

                                    StyleHelper.AddPropertyTriggerWithAction( triggerBase, triggerCondition.Property, ref propertyTriggersWithActions );
                                }
                            }
                            else if( dataTrigger != null )
                            {
                                StyleHelper.AddDataTriggerWithAction( triggerBase, dataTrigger.Binding, ref dataTriggersWithActions );
                            }
                            else if( multiDataTrigger != null )
                            {
                                for( int k = 0; k < multiDataTrigger.Conditions.Count; k++ )
                                {
                                    Condition dataCondition = multiDataTrigger.Conditions[k];

                                    StyleHelper.AddDataTriggerWithAction( triggerBase, dataCondition.Binding, ref dataTriggersWithActions );
                                }
                            }
                            else
                            {
                                throw new InvalidOperationException(SR.Get(SRID.UnsupportedTriggerInTemplate, triggerBase.GetType().Name));
                            }
                        }
                    }
                    else if( eventTrigger != null )
                    {
                        StyleHelper.ProcessEventTrigger(eventTrigger,
                                                        childIndexFromChildID,
                                                        ref triggerActions,
                                                        ref eventDependents,
                                                        templateRoot,
                                                        frameworkTemplate,
                                                        ref eventHandlersStore,
                                                        ref hasLoadedChangeHandler);
                    }
                    else
                    {
                        throw new InvalidOperationException(SR.Get(SRID.UnsupportedTriggerInTemplate, triggerBase.GetType().Name));
                    }
                }
            }
        }
コード例 #5
0
        //
        //  This method
        //  1. Is invoked when Styled/Templated container property invalidation
        //     is propagated to its dependent properties from Style/Template.
        //
        internal static void OnTriggerSourcePropertyInvalidated(
            Style                                                       ownerStyle,
            FrameworkTemplate                                           frameworkTemplate,
            DependencyObject                                            container,
            DependencyProperty                                          dp,
            DependencyPropertyChangedEventArgs                          changedArgs,
            bool                                                        invalidateOnlyContainer,
            ref FrugalStructList<ItemStructMap<TriggerSourceRecord>>    triggerSourceRecordFromChildIndex,
            ref FrugalMap                                               propertyTriggersWithActions,
            int                                                         sourceChildIndex)
        {
            Debug.Assert(ownerStyle != null || frameworkTemplate != null );

            ///////////////////////////////////////////////////////////////////
            // Update all values affected by property trigger Setters

            // Check if this Child Index is represented in given data-structure
            if ((0 <= sourceChildIndex) && (sourceChildIndex < triggerSourceRecordFromChildIndex.Count))
            {
                // Fetch the triggerSourceRecordMap for the given childIndex
                ItemStructMap<TriggerSourceRecord> triggerSourceRecordMap = triggerSourceRecordFromChildIndex[sourceChildIndex];

                // Check if this Container property is represented in style
                int mapIndex = triggerSourceRecordMap.Search(dp.GlobalIndex);
                if (mapIndex >= 0)
                {
                    // Container's property is represented in style
                    TriggerSourceRecord record = triggerSourceRecordMap.Entries[mapIndex].Value;

                    // Invalidate all Self/Child-Index/Property dependents
                    InvalidateDependents(ownerStyle, frameworkTemplate, container, dp,
                        ref record.ChildPropertyDependents, invalidateOnlyContainer);
                }
            }

            ///////////////////////////////////////////////////////////////////
            // Find all TriggerActions that may need to execute in response to
            //  the property change.
            object candidateTrigger = propertyTriggersWithActions[dp.GlobalIndex];

            if( candidateTrigger != DependencyProperty.UnsetValue )
            {
                // One or more trigger objects need to be evaluated.  The candidateTrigger
                //  object may be a single trigger or a collection of them.

                TriggerBase triggerBase = candidateTrigger as TriggerBase;
                if( triggerBase != null )
                {
                    InvokePropertyTriggerActions( triggerBase, container, dp, changedArgs, sourceChildIndex,
                        ownerStyle, frameworkTemplate );
                }
                else
                {
                    Debug.Assert(candidateTrigger is List<TriggerBase>, "Internal data structure error: The FrugalMap [Style/Template].PropertyTriggersWithActions " +
                        "is expected to hold a single TriggerBase or a List<T> of them.  An object of type " +
                        candidateTrigger.GetType().ToString() + " is not expected.  Where did this object come from?");

                    List<TriggerBase> triggerList = (List<TriggerBase>)candidateTrigger;

                    for( int i = 0; i < triggerList.Count; i++ )
                    {
                        InvokePropertyTriggerActions( triggerList[i], container, dp, changedArgs, sourceChildIndex,
                            ownerStyle, frameworkTemplate );
                    }
                }
            }
        }