Version: 6000.3
语言: 中文
定义内置类型的 UXML 属性
自定义 UXML 属性

为复杂数据类型定义自定义控件属性

您可以使用属性转换器和 UxmlObject 来支持自定义控件的复杂数据类型属性。

属性转换器

属性转换器将 UxmlAttribute 类型与字符串进行转换。它为常见类型提供了一组内置转换器,例如int,float,bool,stringVector2.对于复杂的数据类型,例如列表或自定义类,您需要创建自定义转换器。

以下 C# 代码示例创建一个名为Person以及一个名为Department.这Department类包含一个Person字段和Person对象。

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace AttributeConverterExample
{
    [Serializable]
    public class Person
    {
        public string name;
        public int age;
        public string nationality;
    }

    [UxmlElement]
    public partial class Department : VisualElement
    {
        [UxmlAttribute]
        public Person manager;

        [UxmlAttribute]
        public List<Person> employees;
    }
}

如果在 UI Builder 中编辑自定义控件,则会收到以下错误消息:

[UxmlElement] 'Department' has a [UxmlAttribute] 'manager' of an unknown type 'Person'. To fix this error, define a custom UxmlAttributeConverter<Person>.

要解决此问题,请为Person继承自UxmlAttributeConverter<Person>并实现ToStringFromStringPerson对象与字符串的对象。以下示例为Person类:


using UnityEditor.UIElements;

namespace AttributeConverterExample
{
    public class PersonConverter : UxmlAttributeConverter<Person>
    {
        const char k_Separator = ':';

        public override string ToString(Person value)
        {
            return $"{value.name}{k_Separator}{value.age}{k_Separator}{value.nationality}";
        }

        public override Person FromString(string value)
        {
            var person = new Person();
            var split = value.Split(k_Separator);
            if (split.Length == 3)
            {
                person.name = split[0];
                person.age = int.Parse(split[1]);
                person.nationality = split[2];
            }
            return person;
        }
    }
}

转换器将这三个值组合成一个字符串格式,模式为[name]:[age]:[nationality].这FromString方法将字符串拆分为三个值,并将它们分配给Person对象。

下面显示了Department元素:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <AttributeConverterExample.Department name="Dunder Mifflin" manager="Michael Scott:58:USA" employees="Dwight Schrute:53:USA,Jim Halpert:44:USA" />
</ui:UXML>

Uxml对象

使用属性转换器时,随着数据类型变得更加复杂或处理大量列表时,生成的字符串会迅速变得复杂且笨拙。为了简化这一点,您可以使用UxmlObjects.

UxmlObjects是从 UXML 实例化的包含 UXML 属性的类。

了解如何使用UxmlObjects,取上一个PersonDepartment类示例,将它们转换为UxmlObjects如以下示例所示:

using System;
using System.Collections.Generic;
using UnityEngine.UIElements;

namespace UxmlObjectExample
{
    [UxmlObject]
    public partial class Person
    {
        [UxmlAttribute]
        public string name;

        [UxmlAttribute]
        public int age;

        [UxmlAttribute]
        public string nationality;
    }

    [UxmlElement]
    public partial class Department : VisualElement
    {
        [UxmlObjectReference("manager")]
        public Person manager;

        [UxmlObjectReference("employees")]
        public List<Person> employees;
    }
}

Personclass 现在类似于自定义元素,并且使用UxmlAttributefor 属性声明,并引入 UxmlObject 属性来表示其状态为UxmlObject.

而不是使用UxmlAttributeUxmlObject字段,此示例使用 UxmlObjectReferencename.该名称指定了UxmlObject.

以前,所有UxmlObjects被存储为元素的直接子级,这会导致当多个UxmlObject场地存在。很难区分是哪一个UxmlObjects属于哪个领域。

UxmlObjectReference属性通过为UxmlObject.此名称对应于 UXML 标签名称。在前面的示例中,manageremployees字段属于Person类。这UxmlObjectReference属性确保Personclass 被正确地分配给manageremployees领域。

下面显示了 UXML 文件中的用法示例:

<ui:UXML xmlns:ui="UnityEngine.UIElements">
    <UxmlObjectExample.Department name="Department One">
        <manager>
            <UxmlObjectExample.Person name="Manager One" age="58" nationality="Canadian">
        </manager>
        <employees>
            <UxmlObjectExample.Person name="Person Two" age="53" nationality="Canadian">
            <UxmlObjectExample.Person name="Person Three" age="44" nationality="Canadian">
        </employees>
    </UxmlObjectExample.Department>
</ui:UXML>

注意: UxmlObjectReferenceFields也适用于接口。但是,您只能分配UxmlObjects实现指定接口。有关使用接口的示例,请参阅 UxmlObjectReferenceAttribute

其他资源

定义内置类型的 UXML 属性
自定义 UXML 属性