UI toolkit custom element attach dropped element inside a child element

Hello, I am making a custom container using the UI toolkit and trying to get the same behavior. For example, in TabView, when I drop a new element inside through the UI builder, it goes inside a container element. How can I do this with my custom container so that when I drop the new element, it goes inside the content element, not in the root?


using UnityEngine;
using UnityEngine.UIElements;



[UxmlElement("container")]
public partial class Container : VisualElement
{
  private VisualElement headerWrapper;
  private Label uiBalance;
  private Label uiTitle;
  private bool _balance;
  [UxmlAttribute("Balance")]
  public bool balance
  {
    get => _balance; set
    {
      if (_balance != value)
      {
        _balance = value;
        UpdateBalanceVisibility();
      }
    }
  }
  private string _title;
  [UxmlAttribute("Title")]
  public string title
  {
    get => _title; set
    {
      if (_title != value)
      {
        _title = value;
        uiTitle.text = value;
      }
    }
  }
  public Container()
  {
    styleSheets.Add(Resources.Load<StyleSheet>("UIStyles/ContainerStyleSheet"));
    VisualElement header = new() { name = "container-header" };
    Button button = new() { text = "Close", name = "close" };
    uiTitle = new() { name = "container-header__title", text = this.title };
    headerWrapper = new() { name = "container-header__wrapper" };
    VisualElement content = new() { name = "container-content" };

    headerWrapper.Add(uiTitle);
    uiBalance = new()
    {
      name = "container-balance",
      text = "Balance: 0$"
    };

    if (_balance)
    {
      headerWrapper.Add(uiBalance);
    }

    header.Add(headerWrapper);
    header.Add(button);
    hierarchy.Add(header);
    hierarchy.Add(content);
  }

  private void UpdateBalanceVisibility()
  {
    if (_balance)
    {
      headerWrapper.Add(uiBalance);
    }
    else
    {
      uiBalance.RemoveFromHierarchy();
    }
  }

}

you can override the contentContainer property to return a reference to the the content element you created in the Container() constructor.

VisualElement m_Content;
public override VisualElement contentContainer => m_Content;
// ...

  public Container()
  {
    // ...
    m_Content = new() { name = "container-content" };

Adding children via hierarchy.Add() will add elements to directly to the parent VisualElement, but now calls to Container.Add() will add children to the contentContainer instead.

2 Likes