| File: System\Windows\Controls\ContainerTracking.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Windows.Controls { /// <summary> /// Represents a node in a linked list used to track active containers. /// Containers should instantiate and references these. /// Parents hold onto the linked list. /// /// The list is iterated in order to call a variety of methods on containers /// in response to changes on the parent. /// </summary> internal class ContainerTracking<T> { internal ContainerTracking(T container) { _container = container; } /// <summary> /// The row container that this object represents. /// </summary> internal T Container { get { return _container; } } /// <summary> /// The next node in the list. /// </summary> internal ContainerTracking<T> Next { get { return _next; } } /// <summary> /// The previous node in the list. /// </summary> internal ContainerTracking<T> Previous { get { return _previous; } } /// <summary> /// Adds this tracker to the list of active containers. /// </summary> /// <param name="root">The root of the list.</param> internal void StartTracking(ref ContainerTracking<T> root) { // Add the node to the root root?._previous = this; _next = root; root = this; } /// <summary> /// Removes this tracker from the list of active containers. /// </summary> /// <param name="root">The root of the list.</param> internal void StopTracking(ref ContainerTracking<T> root) { // Unhook the node from the list _previous?._next = _next; _next?._previous = _previous; // Update the root reference if (root == this) { root = _next; } // Clear the node's references _previous = null; _next = null; } #region Debugging Helpers /// <summary> /// Asserts that the container represented by this tracker is in the list represented by the given root. /// </summary> [Conditional("DEBUG")] internal void Debug_AssertIsInList(ContainerTracking<T> root) { #if DEBUG Debug.Assert(IsInList(root), "This container should be in the tracking list."); #endif } /// <summary> /// Asserts that the container represented by this tracker is not in the list represented by the given root. /// </summary> [Conditional("DEBUG")] internal void Debug_AssertNotInList(ContainerTracking<T> root) { #if DEBUG Debug.Assert(!IsInList(root), "This container shouldn't be in our tracking list"); #endif } #if DEBUG /// <summary> /// Checks that this tracker is present in the list starting with root. It's a linear walk through the list, so should be used /// mostly for debugging /// </summary> private bool IsInList(ContainerTracking<T> root) { ContainerTracking<T> node = root; while (node != null) { if (node == this) { return true; } node = node._next; } return false; } #endif #endregion private T _container; private ContainerTracking<T> _next; private ContainerTracking<T> _previous; } }