Version: Unity 6.0 (6000.0)
语言 : 中文
定义日志记录级别
运行时数据绑定示例

创建自定义绑定类型

您可以创建自定义绑定类型来扩展运行时绑定系统。要创建自定义绑定类型,请创建一个类并从 CustomBinding 类继承该类。

注册和取消注册绑定对象

CustomBinding 似于 IBinding 接口,允许您注册多个绑定实例而不是单个实例。CustomBinding 是一个可扩展性入口点,仅提供 Update 方法来更新绑定。但是,您可以实现以下方法来在注册、取消册绑定以及元素上的数据源上下文发生更改时接收回调:

定义数据源和数据源路径

要定义绑定类型的数据源和数据源路径,请实现 IDataSourceProvider 接口。绑定系统使用此接口提供的 dataSourcedataSourcePath 属性来确定解析的数据源和数据源路径。这些属性称为“本地”,因为它们会覆盖从层级视图中获取的值。重要的是,修改这些“本地”属性不会影响元素本身或其任何后代。

定义更新触发器

默认情况下,绑定系统在每一帧上更新一个 CustomBinding 实例。

要定义更新触发器,请使用以下方法:

  • MarkDirty:将绑定对象设置为 dirty,使其在下一个周期中更新。
  • updateTrigger:使用此 enum 属性可更改绑定的更新方式。
  • BindingResult:使用此方法可自定义更新过程。该 BindingResult 是一个结构,用于指示更新是否成功。它包含一个 status 和一个 message

BindingResult 包含一个 status 和一个 message。以下是 status 的可能值:

  • 成功 (Success):绑定更新成功。如果绑定实例不需要不断更新,则在数据源发生更改或绑定实例根据更新触发器显式标记为“脏”之前不会再次更新。
  • 失败 (Failure):绑定更新不成功。如果绑定实例不需要不断更新,则在数据源发生更改或绑定实例根据更新触发器显式标记为“脏”之前不会再次更新。
  • 进行中 (Pending):绑定更新仍在进行中。系统会自动将绑定实例标记为“脏”,直到收到成功或失败响应。

您可以使用 BindingResult 方法的 Pending 结果来通知绑定系统是否需要在下一个周期更新绑定对象。

示例

本节提供了一个示例,演示如何在__ UI__(即用户界面,User Interface)让用户能够与您的应用程序进行交互。Unity 目前支持三种 UI 系统。更多信息
See in Glossary
Builder、UXML 和 C# 中创建自定义绑定类型和设置绑定。

以下示例创建显示当前时间的自定义绑定类型。您可以将其绑定到标签的 text 属性以创建时钟。

using System;
using Unity.Properties;
using UnityEngine.UIElements;

[UxmlObject]
public partial class CurrentTimeBinding : CustomBinding
{
    [UxmlAttribute]
    public string timeFormat = "HH:mm:ss";

    public CurrentTimeBinding()
    {
        updateTrigger = BindingUpdateTrigger.EveryUpdate;
    }

    protected override BindingResult Update(in BindingContext context)
    {
        var timeNow = DateTime.Now.ToString(timeFormat);
        var element = context.targetElement;
        if (ConverterGroups.TrySetValueGlobal(ref element, context.bindingId, timeNow, out var errorCode))
            return new BindingResult(BindingStatus.Success);

        // Error handling
        var bindingTypename = TypeUtility.GetTypeDisplayName(typeof(CurrentTimeBinding));
        var bindingId = $"{TypeUtility.GetTypeDisplayName(element.GetType())}.{context.bindingId}";

        return errorCode switch
        {
            VisitReturnCode.InvalidPath => new BindingResult(BindingStatus.Failure, $"{bindingTypename}: Binding id `{bindingId}` is either invalid or contains a `null` value."),
            VisitReturnCode.InvalidCast => new BindingResult(BindingStatus.Failure, $"{bindingTypename}: Invalid conversion from `string` for binding id `{bindingId}`"),
            VisitReturnCode.AccessViolation => new BindingResult(BindingStatus.Failure, $"{bindingTypename}: Trying set value for binding id `{bindingId}`, but it is read-only."),
            _ => throw new ArgumentOutOfRangeException()
        };
    }
}

创建自定义绑定类型时,该类型将显示在 UI Builder 的添加绑定 (Add binding) 窗口中。要在 UI Builder 中设置绑定,请在添加绑定 (Add binding) 窗口中从类型 (Type) 列表中选择当前时间绑定 (CurrentTimeBinding)

此绑定的 UXML 等效形式如下:

 <ui:Label text="Label">
    <Bindings>
        <CurrentTimeBinding property="text" />
    </Bindings>
</ui:Label>

此绑定的 C# 等效形式如下:

var label = new Label();
label.SetBinding("text",  new CurrentTimeBinding());

最佳实践

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

  • 最大限度减少每个元素的状态使用量:减少对自定义绑定类型中每个元素状态的依赖。相反,应尽可能利用共享或全局状态来增强性能并简化维护。
  • 使用 BindingUpdateTrigger.OnSourceChanged:如果绑定类型仅在检测到源中发生更改时才需要更新,请将 updateTrigger 设置为 BindingUpdateTrigger.OnSourceChanged。这样可以确保仅在必要时更新绑定类型,从而优化性能。
  • 使用 BindingUpdateTrigger.WhenDirty 进行手动更新:如果手动更新绑定类型并且不需要立即同步,请将 updateTrigger 设置为 BindingUpdateTrigger.WhenDirty。这允许您手动控制绑定类型的更新时间,从而提供对同步的灵活性和控制。
  • 利用回调:尽可能使用 OnActivatedOnDeactivatedOnDataSourceChanged 回调而不是 Update 回调。这些回调在特定生命周期事件中触发,从而减少不必要的更新并提高效率。通过使用适当的回调,可以优化绑定类型的行为并确保在需要时准确进行更新。

其他资源

定义日志记录级别
运行时数据绑定示例