Version: 1.6
语言 : 中文
运行时绑定入门
定义用于运行时绑定的数据源

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

要将视觉元素的属性绑定到C#中的数据源,请创建一个DataSource实例。使用此绑定类型,您可以直接在绑定实例上定义DataSourceDataSourcePath

基本工作流程

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

  1. 创建一个绑定。绑定是您可以通过唯一的ID创建,注册或注册视觉元素的对象。

  2. 定义数据源以及绑定对象的数据源路径。数据源是包含要绑定到的属性的对象。数据源路径是从数据源到您要绑定到的属性的相对路径。

  3. 定义绑定模式并更新触发器对于绑定对象。绑定模式定义了如何在数据源和 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 reuse 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这标识了更改的属性。

以下示例显示了如何报告一个更改VisualElement类型:

// 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必须是元素的目标属性。例如,如果您想绑定到value属性Vector3Field,绑定ID必须是Vector3Field.valueProperty

  • 避免使用绑定的内部数据更新 :不要使用绑定来更新视觉元素的内部数据。例如,不要使用绑定来同步xyz的子元素Vector3Field。而是使用绑定来同步value属性Vector3FieldVector3数据源的属性。

已知限制

UI工具包没有报告更改element.styleelement.resolvedStyle。因此,您可以使用绑定实例来定位元素的分辨样式,但无法跟踪其更改。

其他资源

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