private IncrementalUpdater FindUpdater()
        {
            if (this.updater != null)
            {
                return(this.updater);
            }

            DependencyObject ancestor = this.associatedObject;

            while (ancestor != null)
            {
                DependencyObject parent   = VisualTreeHelper.GetParent(ancestor);
                ListViewBase     listView = parent as ListViewBase;

                if (listView != null)
                {
                    IncrementalUpdater currentUpdater = IncrementalUpdateBehavior.GetIncrementalUpdater(listView);
                    if (currentUpdater == null)
                    {
                        currentUpdater = new IncrementalUpdater();

                        IncrementalUpdateBehavior.SetIncrementalUpdater(listView, currentUpdater);
                    }
                    return(currentUpdater);
                }
                ancestor = parent;
            }

            return(null);
        }
        private void OnAssociatedObjectUnloaded(object sender, RoutedEventArgs e)
        {
            if (this._updater != null)
            {
                this._updater.UncachePhaseElement(this.AssociatedObject, this.Phase);
            }

            this._updater = null;
        }
        private void OnAssociatedObjectLoaded(object sender, RoutedEventArgs e)
        {
            IncrementalUpdater incrementalUpdater = this.FindUpdater();

            if (incrementalUpdater != null)
            {
                incrementalUpdater.CachePhaseElement(this.AssociatedObject, this.Phase);
            }
        }
        private void OnAssociatedObjectLoaded(object sender, RoutedEventArgs e)
        {
            IncrementalUpdater incrementalUpdater = this.FindUpdater();
            FrameworkElement   frameworkElement   = (FrameworkElement)this.associatedObject;

            if (incrementalUpdater != null && frameworkElement != null)
            {
                incrementalUpdater.CachePhaseElement(frameworkElement, this.Phase);
            }
        }
        private void OnAssociatedObjectUnloaded(object sender, RoutedEventArgs e)
        {
            FrameworkElement frameworkElement = (FrameworkElement)this.associatedObject;

            if (this.updater != null && frameworkElement != null)
            {
                this.updater.UncachePhaseElement(frameworkElement, this.Phase);
            }

            this.updater = null;
        }
        private static void OnPhaseChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
        {
            IncrementalUpdateBehavior behavior           = (IncrementalUpdateBehavior)sender;
            IncrementalUpdater        incrementalUpdater = behavior.FindUpdater();
            FrameworkElement          frameworkElement   = behavior.associatedObject as FrameworkElement;

            if (incrementalUpdater != null && frameworkElement != null)
            {
                incrementalUpdater.UncachePhaseElement(frameworkElement, (int)args.OldValue);
                incrementalUpdater.CachePhaseElement(frameworkElement, (int)args.NewValue);
            }
        }
 private static void OnIncrementalUpdaterChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
 {
     if (args.OldValue != null)
     {
         IncrementalUpdater incrementalUpdater = (IncrementalUpdater)args.OldValue;
         incrementalUpdater.Detach();
     }
     if (args.NewValue != null)
     {
         IncrementalUpdater incrementalUpdater = (IncrementalUpdater)args.NewValue;
         incrementalUpdater.Attach(sender);
     }
 }
            public void CachePhaseElement(FrameworkElement phaseElement, int phase)
            {
                if (phase < 0)
                {
                    throw new ArgumentOutOfRangeException("phase");
                }

                if (phase <= 0)
                {
                    return;
                }

                UIElement contentTemplateRoot = IncrementalUpdater.FindContentTemplateRoot(phaseElement);

                if (contentTemplateRoot != null)
                {
                    // get the cache for this element
                    ElementCacheRecord elementCacheRecord;
                    if (!this.elementCache.TryGetValue(contentTemplateRoot, out elementCacheRecord))
                    {
                        elementCacheRecord = new ElementCacheRecord();
                        this.elementCache.Add(contentTemplateRoot, elementCacheRecord);
                    }

                    // get the cache for this phase
                    int phaseIndex = elementCacheRecord.Phases.BinarySearch(phase);

                    if (phaseIndex < 0)
                    {
                        // not found - insert
                        phaseIndex = ~phaseIndex;
                        elementCacheRecord.Phases.Insert(phaseIndex, phase);
                        elementCacheRecord.ElementsByPhase.Insert(phaseIndex, new List <PhasedElementRecord>());
                    }

                    List <PhasedElementRecord> phasedElementRecords = elementCacheRecord.ElementsByPhase[phaseIndex];

                    // first see if the element is already there
                    for (int i = 0; i < phasedElementRecords.Count; i++)
                    {
                        if (phasedElementRecords[i].FrameworkElement == phaseElement)
                        {
                            return;
                        }
                    }

                    // insert the element
                    phasedElementRecords.Add(new PhasedElementRecord(phaseElement));
                }
            }
            public void UncachePhaseElement(FrameworkElement phaseElement, int phase)
            {
                if (phase <= 0)
                {
                    return;
                }

                UIElement contentTemplateRoot = IncrementalUpdater.FindContentTemplateRoot(phaseElement);

                if (contentTemplateRoot != null)
                {
                    // get the cache for this element
                    ElementCacheRecord elementCacheRecord;
                    if (this.elementCache.TryGetValue(contentTemplateRoot, out elementCacheRecord))
                    {
                        // get the cache for this phase
                        int phaseIndex = elementCacheRecord.Phases.BinarySearch(phase);

                        if (phaseIndex >= 0)
                        {
                            // remove the element: the linear search here is not spectacular but the list should be very short
                            List <PhasedElementRecord> phasedElementRecords = elementCacheRecord.ElementsByPhase[phaseIndex];

                            for (int i = 0; i < phasedElementRecords.Count; i++)
                            {
                                if (phasedElementRecords[i].FrameworkElement == phaseElement)
                                {
                                    phasedElementRecords[i].ThawAndShow();

                                    phasedElementRecords.RemoveAt(i);

                                    if (phasedElementRecords.Count == 0)
                                    {
                                        elementCacheRecord.Phases.RemoveAt(phaseIndex);
                                        elementCacheRecord.ElementsByPhase.RemoveAt(phaseIndex);
                                    }
                                }
                            }
                        }
                    }
                }
            }
 private static void SetIncrementalUpdater(DependencyObject dependencyObject, IncrementalUpdater value)
 {
     dependencyObject.SetValue(IncrementalUpdateBehavior.IncrementalUpdaterProperty, value);
 }
        private void OnAssociatedObjectUnloaded(object sender, RoutedEventArgs e)
        {
            FrameworkElement frameworkElement = (FrameworkElement)this.associatedObject;

            if (this.updater != null && frameworkElement != null)
            {
                this.updater.UncachePhaseElement(frameworkElement, this.Phase);
            }

            this.updater = null;
        }
        private IncrementalUpdater FindUpdater()
        {
            if (this.updater != null)
            {
                return this.updater;
            }

            DependencyObject ancestor = this.associatedObject;
            while (ancestor != null)
            {
                DependencyObject parent = VisualTreeHelper.GetParent(ancestor);
                ListViewBase listView = parent as ListViewBase;

                if (listView != null)
                {
                    IncrementalUpdater currentUpdater = IncrementalUpdateBehavior.GetIncrementalUpdater(listView);
                    if (currentUpdater == null)
                    {
                        currentUpdater = new IncrementalUpdater();

                        IncrementalUpdateBehavior.SetIncrementalUpdater(listView, currentUpdater);
                    }
                    return currentUpdater;
                }
                ancestor = parent;
            }

            return null;
        }
 private static void SetIncrementalUpdater(DependencyObject dependencyObject, IncrementalUpdater value)
 {
     dependencyObject.SetValue(IncrementalUpdateBehavior.IncrementalUpdaterProperty, value);
 }
 private void OnDisable()
 {
     IncrementalUpdater.RemoveObject <PhysicsPassthroughScanner>(this, UpdateStep.FixedUpdate);
 }
 private void OnEnable()
 {
     IncrementalUpdater.RegisterObject <PhysicsPassthroughScanner>(this, UpdateBounds, UpdateStep.FixedUpdate);
 }