版本:2022.3
语言:英语
创建自定义控件
自定义UXML标签名称和属性

将自定义控件暴露给UXML和UI构建器

要使用UXML和UI构建器中的自定义控件,必须将其暴露。

定义工厂

为了定义新元素,需要从《VisualElement》或其子类派生一个新类,然后在新的类中实现适当的功能。

您的新类必须实现一个默认构造函数。例如

class StatusBar : VisualElement
{
    public StatusBar()
    {
        m_Status = String.Empty;
    }

    string m_Status;
    public string status { get; set; }
}

为了让UI工具包在读取UXML文件时可以实例化新的类,您必须为您的类定义一个工厂。除非您的工厂需要做特殊处理,否则可以从《UxmlFactory`>派生工厂。建议将工厂类放在您的组件类中。

例如,以下代码段为《StatusBar`类定义了一个名为《UxmlFactory`>的工厂。

class StatusBar : VisualElement
{
    public new class UxmlFactory : UxmlFactory<StatusBar> {}

    // ...
}

定义了此工厂后,您可以在UXML文件中使用《`元素。

在元素上定义属性

您可以定义新类的UXML属性并设置其工厂使用这些属性。

例如,以下代码段定义了一个UXML属性类来初始化《StatusBar`类的《status`属性。该属性从UXML数据初始化。

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

    public new class UxmlTraits : VisualElement.UxmlTraits
    {
        UxmlStringAttributeDescription m_Status = new UxmlStringAttributeDescription { name = "status" };

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

        public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
        {
            base.Init(ve, bag, cc);
            ((StatusBar)ve).status = m_Status.GetValueFromBag(bag, cc);
        }
    }

    // ...
}

注意:在UI构建器内创建元素时,UI构建器可能会多次调用《UxmlTraits.Init()`》以同步UXML文件中的值。建议使用《GetValueFromBag()`》而不是《TryGetValueFromBag()`》以确保当在UI构建器中取消设置属性时,元素不会保留上一个值。

《UxmlTraits`>有两个用途

  • 工厂使用它来初始化新创建的对象。
  • 模式生成过程分析它以获取关于元素的信息。这些信息转换为XML模式指令。

上面的代码示例做了以下操作

  • 《m_Status`>的声明定义了一个名为《status`>的XML属性。
  • 《uxmlChildElementsDescription`>返回一个空的《IEnumerable`>,表示《StatusBar`元素没有任何子元素。
  • 《Init()`成员从XML解析器的属性包中读取《status`属性值并将其设置为《StatusBar.status`>属性。
  • 将《UxmlTraits`>类放在《StatusBar`>类内部。这使得《Init()`方法可以访问《StatusBar`>的私有成员。
  • 新的《UxmlTraits`类从基类《UxmlTraits`>继承,因此它共享基类的属性。
  • 《Init()`调用`base.Init()`来初始化基类的属性。

上面的代码示例声明了一个具有《UxmlStringAttributeDescription`>`类的字符串属性。UI工具包支持以下类型的属性,并且每个都链接C#类型和UMXL类型

属性 属性值
UxmlStringAttributeDescription 字符串
UxmlFloatAttributeDescription C#《float`>类型的单精度浮点值。
UxmlDoubleAttributeDescription C#《double`>类型的双精度浮点值。
UxmlIntAttributeDescription C# int 类型的整数值。
UxmlLongAttributeDescription C# long 类型的长整数值。
UxmlBoolAttributeDescription truefalse
UxmlColorAttributeDescription 表示 USS 格式中定义的颜色字符串。
UxmlEnumAttributeDescription<T> 表示类型 Enum T 的一个值字符串。
UxmlTypeAttributeDescription<T> 表示类型的程序集限定名称字符串。

在上面的代码示例中,uxmlChildElementsDescription 返回一个空的 IEnumerable,这表示 StatusBar 元素不接受 XML 架构的子元素描述。

要让元素接受任何类型的子元素,必须重写 uxmlChildElementsDescription 属性。例如,要让 StatusBar 元素接受任何类型的子元素,必须将 uxmlChildElementsDescription 属性指定如下:

public override IEnumerable<UxmlChildElementDescription> uxmlChildElementsDescription
{
    get
    {
        yield return new UxmlChildElementDescription(typeof(VisualElement));
    }
}

定义命名空间前缀

在 C# 中定义了一个新元素之后,您可以在您的 UXML 文件中使用该元素。为了分类元素,请在命名空间中创建您的类。当您定义一个新的命名空间时,可以为该命名空间定义一个前缀。您必须定义命名空间前缀,作为根 <UXML> 元素的属性,并在范围期间替换完整的命名空间名称。

要定义命名空间前缀,为每个命名空间前缀向您的程序集添加一个 UxmlNamespacePrefix 属性。例如:

[assembly: UxmlNamespacePrefix("My.First.Namespace", "first")]
[assembly: UxmlNamespacePrefix("My.Second.Namespace", "second")]

您可以在程序集的根级别(任何命名空间外)的任何 C# 文件中执行此操作。

模式生成系统执行以下操作:

  • 检查这些属性并使用它们来生成模式。
  • 在新创建的 UXML 文件中将命名空间前缀定义为 <UXML> 元素的属性。
  • 在它的 xsi:schemaLocation 属性中包括命名空间的模式文件位置。

为确保您的文本编辑器能够识别新元素,请选择 资源 > 更新 UXML 模式 以更新模式定义。

要使用前缀创建新的 UXML 文档,请选择 资源 > 创建 > UI 工具包 > UI 文档

其他资源

创建自定义控件
自定义UXML标签名称和属性