版本:Unity 6 (6000.0)
语言:English
运行时绑定的入门
为运行时绑定定义数据源

在 C# 脚本中创建运行时绑定

要将视觉元素可视化树中的节点,它实例化或派生自 C# VisualElement 类。您可以设置外观样式、定义行为并在屏幕上将其显示为 UI 的一部分。 更多信息
参见 术语表
的属性绑定到 C# 中的数据源,请创建 DataBinding 的实例。使用此绑定类型,您可以在绑定实例上直接定义 dataSourcedataSourcePath

基本工作流程

要在 C# 中创建运行时绑定,请按照以下步骤操作

  1. 创建绑定。绑定是可以创建、注册或注销到视觉元素的对象,它们通过唯一的 ID 进行识别。
  2. 定义数据源和绑定对象的数据源路径。数据源是包含要绑定到的属性的对象。数据源路径是从数据源到要绑定到的属性的相对路径。
  3. 定义绑定模式和更新触发器以绑定对象。绑定模式定义了如何在数据源和UI(用户界面) 允许用户与您的应用程序交互。Unity 目前支持三个 UI 系统。 更多信息
    参见 术语表
    之间复制更改。更新触发器定义何时更新绑定对象。
  4. 将绑定对象注册到视觉元素。
  5. 如有必要,添加类型转换器以在数据源和 UI 之间转换数据类型

以下示例创建了一个绑定对象并将其注册到一个视觉元素。

var dataSource = ScriptableObject.CreateInstance<ExampleObject>();

var root = new VisualElement
{
    name = "root",
    dataSource = dataSource
};

var vector3Field = new Vector3Field("Vec3 Field");

vector3Field.SetBinding("label", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.vector3Label)),
    bindingMode = BindingMode.ToTarget
});

vector3Field.SetBinding("value", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.vector3Value))
});

root.Add(vector3Field);

var floatField = new FloatField("Float Field") { value = 42.2f };

floatField.SetBinding("value", new DataBinding
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.sumOfVector3Properties))
});

root.Add(floatField);

var label = new Label("Label")
{
    dataSourcePath = new PropertyPath(nameof(ExampleObject.dangerLevel))
};

// Here, we do not need to set the dataSourcePath because we will only use two bindings and they will use the same path,
// so we set the dataSourcePath on the Label directly instead.
var binding = new DataBinding
{
    bindingMode = BindingMode.ToTarget
};

// Add a custom float -> string converter
binding.sourceToUiConverters.AddConverter((ref float v) => 
{
    return v switch
    {
        >= 0 and < 1.0f/3.0f => "Danger",
        >= 1.0f/3.0f and < 2.0f/3.0f => "Neutral",
        _ => "Good"
    };
});

// Add a custom float -> StyleColor
binding.sourceToUiConverters.AddConverter((ref float v) => new StyleColor(Color.Lerp(Color.red, Color.green, v)));

// Since the binding is targeting the same data source property, we can re-use the same instance.
label.SetBinding("text", binding);
label.SetBinding("style.backgroundColor", binding);

root.Add(label);

它等效于以下 UXML

<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" 
editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
    <ui:VisualElement data-source="ExampleObject.asset" name="VisualElement" >
        <ui:Vector3Field label="Vec3 Field">
            <Bindings>
                <ui:DataBinding property="label" data-source-path="vector3Label" binding-mode="ToSource" />
                <ui:DataBinding property="value" data-source-path="vector3Value" />
            </Bindings>
        </ui:Vector3Field>
        <ui:FloatField label="Float Field" value="42.2">
            <Bindings>
                <ui:DataBinding property="value" data-source-path="sumOfVector3Properties" binding-mode="ToTarget" />
            </Bindings>
        </ui:FloatField>
        <ui:Label text="Label" data-source-path="dangerLevel">
            <Bindings>
                <ui:DataBinding property="text" binding-mode="ToTarget" source-to-ui-converters="Value To Progress" />
                <ui:DataBinding property="style.backgroundColor" binding-mode="ToTarget" source-to-ui-converters="Value To Progress" />
            </Bindings>
    </ui:Label>
    </ui:VisualElement>
</ui:UXML>

注册和注销绑定对象

您可以使用以下方法来管理绑定对象

报告更改

您可以像其他数据源一样创建可绑定属性,这意味着您也可以使用 VisualElement 类型作为数据源VisualElement 类型和其他数据源之间的主要区别在于 VisualElement 类型具有内置版本控制。您必须使用 VisualElement 类型的内置版本控制来传播更改。

要报告更改,请调用 NotifyPropertyChanged 方法。此方法采用 BindingId,该 ID 标识已更改的属性。以下示例显示了如何报告更改

// Creates a static readonly BindingId that is unique to this type. This is used to identify the property. 
public static readonly BindingId intValueProperty = nameof(intValue);

private int m_IntValue;

[CreateProperty]
public int intValue
{
    get => m_IntValue;
    set
    {
        if (m_IntValue == value)
            return;
        m_IntValue = value;
        
        // This instructs the binding system that a change occured.
        NotifyPropertyChanged(intValueProperty);
    }
}

最佳实践

遵循以下提示和最佳实践以优化性能

  • 使用正确的绑定 ID:绑定系统使用绑定 ID 来识别绑定对象和元素的目标属性。绑定 ID 必须是元素的目标属性。例如,如果您想绑定到 Vector3Fieldvalue 属性,则绑定 ID 必须为 Vector3Field.valueProperty
  • 避免使用绑定进行内部数据更新:不要使用绑定来更新视觉元素的内部数据。例如,不要使用绑定来同步 Vector3Fieldxyz 子元素。相反,请使用绑定来同步 Vector3Fieldvalue 属性与数据源的 Vector3 属性。

已知限制

UI 工具包不会报告 element.styleelement.resolvedStyle 中的更改。因此,您可以使用绑定实例来定位元素的已解析样式,但无法跟踪对它们的更改。

其他资源

运行时绑定的入门
为运行时绑定定义数据源