Version: 2021.2
Structuring UXML attributes
Styling UI

Using custom (C#) elements

Custom C# elements are a way to embed complex UI-related functionality directly in the UI code. For example, take the IntegerField control. This is a single custom C# element that appears and behaves like a single element in both UXML and in UI Builder, but internally it creates a hierarchy of elements that manages user input, data validation, and data bindings.

You can create a new custom C# element in C# by inheriting from the VisualElement class. This will allow you to create and use this element in C# but won’t automatically expose it in UXML and UI Builder. To expose your new element type in UXML and UI Builder, you need to define the UxmlFactory, like this:

class MyElement : VisualElement
{
    public new class UxmlFactory : UxmlFactory<MyElement, UxmlTraits> { }
}

After you add the UxmlFactory to your class, you will be able to create your element in UXML via the <MyElement> tag and find it in the UI Builder’s Library, under the Project tab, in the Custom Controls (C#) section. Further categorization will be created if your class is in a namespace.

You can expose additional custom UXML attributes like this:

class MyElement : VisualElement
{
    public new class UxmlFactory : UxmlFactory<MyElement, UxmlTraits> { }

    public new class UxmlTraits : VisualElement.UxmlTraits
    {
        UxmlStringAttributeDescription m_String =
            new UxmlStringAttributeDescription { name = "string-attr", defaultValue = "default_value" };
        UxmlIntAttributeDescription m_Int =
            new UxmlIntAttributeDescription { name = "int-attr", defaultValue = 2 };

        public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
        {
            get { yield break; }
        }

        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
        {
            base.Init(ve, bag, cc);
            var ate = ve as MyElement;

            ate.stringAttr = m_String.GetValueFromBag(bag, cc);
            ate.intAttr = m_Int.GetValueFromBag(bag, cc);
        }
    }

    public string stringAttr { get; set; }
    public int intAttr { get; set; }
}

UI Builder adds one additional requirement on top of what’s already required for pure UXML attributes to work. UI Builder requires your element class to expose a { get; set; } C# property that has the same name as the name you set in your Uxml*AttributeDescription, except instead of dashes, the C# property name needs to be using camelCasing. For example, if your UXML attribute is named my-int, the C# property name should be myInt. This is because the UI Builder relies on these C# properties to read the value of the C# attributes to populate its Inspector pane.

Here are the above custom attributes displayed in the Inspector pane:

CustomElementAttributes
CustomElementAttributes

UI Builder currently doesn’t support custom Inspectors for custom C# elements.

Structuring UXML attributes
Styling UI