# BindViewItem

> Raised when a HierarchyViewItem is bound to a HierarchyView. Use this event to customize the view item.

## Definition

* **Type:** Event
* **Namespace:** [Unity.Hierarchy](/engine/6000.7/script-reference/unity/hierarchy.md)
* **Assembly:** UnityEngine.HierarchyModule

```csharp
public event HierarchyView.BindViewItemEventHandler BindViewItem
```

### Remarks

The following example draws visual connector lines in the Hierarchy window to show the parent and child relationships between GameObjects. It uses the instance-level `BindViewItem` event to register a per-view binding handler that adds the visual connector lines between each parent and child item in the Hierarchy window.

The example requires three USS files: `Connectors.uss` for the base styles, `Connectors_dark.uss` for the Dark theme, and `Connectors_light.uss` for the Light theme.

To use this example, save the script and USS files in a folder called `Assets/Editor/Connectors`. Scripts in an `Editor` folder can use the Hierarchy module API without additional setup. If you save the script outside of an `Editor` folder, you must enable the Hierarchy built-in module in the **Package Manager** window, which also adds the module to your Player builds.

```csharp
using System;
using System.Collections.Generic;
using Unity.Hierarchy;
using Unity.Hierarchy.Editor;
using UnityEditor;
using UnityEngine.Pool;
using UnityEngine.UIElements;

namespace Unity.HierarchySamples.Editor
{
    class Connectors
    {
        const string k_ConnectorUssClassName = "connector";
        const string k_ConnectorHoverUssClassName = "connector--hovered";
        const string k_ConnectorContainerClassName = "connector-container";

        [InitializeOnLoadMethod]
        static void Initialize()
        {
            HierarchyWindow.BindView += OnBindView;
            HierarchyWindow.UnbindView += OnUnbindView;
        }

        static void OnBindView(HierarchyWindow window, HierarchyView view)
        {
            view.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Editor/Connectors/Connectors.uss"));
            view.styleSheets.Add(AssetDatabase.LoadAssetAtPath<StyleSheet>($"Assets/Editor/Connectors/Connectors{(EditorGUIUtility.isProSkin ? "_dark" : "_light")}.uss"));

            ConnectorsHandler connectorHandler = new ConnectorsHandler(view);
            view.BindViewItem += connectorHandler.OnBindViewItem;
            view.userData = connectorHandler;
        }

        static void OnUnbindView(HierarchyWindow window, HierarchyView view)
        {
            if (view.userData is ConnectorsHandler connectorHandler)
                view.BindViewItem -= connectorHandler.OnBindViewItem;
        }

        class ConnectorsHandler
        {
            static readonly List<VisualElement> s_ConnectorsCache = new();
            static readonly ObjectPool<VisualElement> s_ConnectorVisualElementPool = new(() => new VisualElement(), actionOnRelease: e => e.userData = null);

            readonly HierarchyView m_View;

            int m_HoverDepth = -1;

            internal ConnectorsHandler(HierarchyView view) => m_View = view;

            internal void OnBindViewItem(HierarchyView view, HierarchyViewItem viewItem)
            {
                HierarchyViewModel viewModel = view.ViewModel;
                VisualElement connectorContainer = viewItem.Q(className: k_ConnectorContainerClassName);
                if (connectorContainer == null)
                {
                    connectorContainer = new VisualElement();
                    connectorContainer.AddToClassList(k_ConnectorContainerClassName);
                    viewItem.Add(connectorContainer);
                }

                s_ConnectorsCache.Clear();
                connectorContainer.Query(className: k_ConnectorUssClassName).ToList(s_ConnectorsCache);

                // Depth is 0 when filtering because the tree is flattened
                int nodeDepth = view.Filtering ? 0 : viewModel.GetDepth(viewItem.Node);
                HierarchyNode nodeParent = viewModel.GetParent(viewItem.Node);
                bool parentHasHoveredFlag = viewModel.HasFlags(nodeParent, (HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered);

                for (int i = 0; i < nodeDepth; i++)
                {
                    VisualElement connector;
                    if (i < s_ConnectorsCache.Count)
                    {
                        connector = s_ConnectorsCache[i];
                    }
                    else
                    {
                        connector = s_ConnectorVisualElementPool.Get();
                        connector.AddToClassList(k_ConnectorUssClassName);
                        connectorContainer.Add(connector);
                        connector.RegisterCallback<MouseEnterEvent>(OnMouseEnter);
                        connector.RegisterCallback<MouseLeaveEvent>(OnMouseLeave);
                        connector.RegisterCallback<MouseDownEvent>(OnConnectorPressed);
                    }

                    connector.userData = (viewItem, i);
                    connector.style.left = i * 14;
                    connector.EnableInClassList(k_ConnectorHoverUssClassName, parentHasHoveredFlag && i == m_HoverDepth);
                }

                for (int i = nodeDepth; i < s_ConnectorsCache.Count; i++)
                {
                    VisualElement connector = s_ConnectorsCache[i];
                    connector.RemoveFromHierarchy();
                    connector.UnregisterCallback<MouseEnterEvent>(OnMouseEnter);
                    connector.UnregisterCallback<MouseLeaveEvent>(OnMouseLeave);
                    connector.UnregisterCallback<MouseDownEvent>(OnConnectorPressed);
                    s_ConnectorVisualElementPool.Release(connector);
                }
            }

            static (HierarchyViewItem viewItem, int depth) GetConnectorData(EventBase evt) =>
                ((HierarchyViewItem, int))((VisualElement)evt.currentTarget).userData;

            void OnMouseEnter(MouseEnterEvent evt)
            {
                (HierarchyViewItem viewItem, int depth) = GetConnectorData(evt);
                m_HoverDepth = depth;
                HierarchyNode ancestor = GetAncestorAtDepth(viewItem, depth);
                viewItem.View.ViewModel.SetFlagsRecursive(ancestor, (HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered, HierarchyTraversalDirection.Children);
            }

            void OnMouseLeave(MouseLeaveEvent evt)
            {
                m_HoverDepth = -1;
                m_View.ViewModel.ClearFlags((HierarchyNodeFlags)HierarchyNodeFlagsExtended.ConnectorsHovered);
            }

            void OnConnectorPressed(MouseDownEvent evt)
            {
                (HierarchyViewItem viewItem, int depth) = GetConnectorData(evt);
                HierarchyNode ancestor = GetAncestorAtDepth(viewItem, depth);
                if (evt.altKey)
                    viewItem.View.ViewModel.ClearFlagsRecursive(ancestor, HierarchyNodeFlags.Expanded, HierarchyTraversalDirection.Children);
                else
                    viewItem.View.ViewModel.ClearFlags(ancestor, HierarchyNodeFlags.Expanded);
            }

            HierarchyNode GetAncestorAtDepth(HierarchyViewItem viewItem, int depth)
            {
                HierarchyNode ancestor = viewItem.Node;
                for (int i = viewItem.View.ViewModel.GetDepth(viewItem.Node); i > depth; i--)
                    ancestor = viewItem.View.ViewModel.GetParent(ancestor);

                return ancestor;
            }
        }

        // Custom flags can be defined by using unused bits in the HierarchyNodeFlags enum.
        // This example uses bit 4 to track hover state for connector visualization.
        enum HierarchyNodeFlagsExtended : uint
        {
            ConnectorsHovered = 1 << 4
        }
    }
}
```

The following example shows how to style `Connectors.uss`.

```csharp
.connector {
    width: 10px;
    border-left-width: 1px;
    height: 100%;
    position: absolute;
}

.connector-container {
    position: absolute;
    left: 12px;
    top: 0;
    background-color: chartreuse;
    height: 20px;
    width: auto;
}

.connector.connector--hovered{
    border-left-width: 1px;
}
```

The following example shows how to style `Connectors_dark.uss`.

```csharp
.connector {
    border-left-color: rgba(169, 169, 169, 0.42);
}

.connector.connector--hovered{
    border-left-color: darkgrey;
}
```

The following example shows how to style `Connectors_light.uss`.

```csharp
.connector {
    border-left-color: darkgrey;
}

.connector.connector--hovered{
    border-left-color: grey;
}
```
