Create a runtime binding in C# scripts
Create a runtime data binding.
阅读时间4 分钟最后更新于 21 天前
To bind a property of a visual element to a data source in C#, create an instance of . With this binding type, you can define a and a directly on the binding instance.
DataBindingdataSourcedataSourcePathBasic workflow
To create a runtime binding in C#, follow these steps:
- Create a binding. Bindings are objects that you can create, register, or unregister to a visual element through a unique ID.
- Define the data source and the data source path for the binding object. The data source is the object that contains the property you want to bind to. The data source path is a relative path from the data source to the property you want to bind to.
- Define the binding mode and update triggers for the binding object. The binding mode defines how changes are replicated between the data source and the UI. The update trigger defines when to update the binding object.
- Register the binding object to the visual element.
- If necessary, add type converters to convert data types between the data source and the UI.
Assume you have a data source object named that contains a property named and a property named , which is the sum of the , , and components of the property. For more information about this data source object, refer to the Create a data source asset section of the Bind to multiple properties with runtime binding example.
ExampleMultiPropertiesObjectVector3vector3ValuefloatsumOfVector3Propertiesxyzvector3ValueYou can then create a binding object and register it to a visual element as follows:
using Unity.Properties;using UnityEngine;using UnityEngine.UIElements;public class RuntimeBindingExample{ public VisualElement CreateBindingExample() { var dataSource = ScriptableObject.CreateInstance<ExampleMultiPropertiesObject>(); var root = new VisualElement { name = "root", dataSource = dataSource }; var vector3Field = new Vector3Field("Vec3 Field"); vector3Field.SetBinding("value", new DataBinding { dataSourcePath = new PropertyPath(nameof(ExampleMultiPropertiesObject.vector3Value)) }); root.Add(vector3Field); var floatField = new FloatField("Float Field") { value = 42.2f }; floatField.SetBinding("value", new DataBinding { dataSourcePath = new PropertyPath(nameof(ExampleMultiPropertiesObject.sumOfVector3Properties)) }); root.Add(floatField); return root; }}
It's equivalent to the following UXML:
<engine:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:engine="UnityEngine.UIElements" xmlns:editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False"> <engine:VisualElement data-source="MulPropertyObject.asset" name="VisualElement" style="flex-grow: 1;"> <engine:Vector3Field label="Vec3 Field"> <Bindings> <engine:DataBinding property="value" data-source-path="vector3Value" binding-mode="ToSource"/> </Bindings> </engine:Vector3Field> <engine:FloatField label="Float Field" name="FloatField"> <Bindings> <engine:DataBinding property="value" data-source-path="sumOfVector3Properties" binding-mode="ToTarget"/> </Bindings> </engine:FloatField> </engine:VisualElement></engine:UXML>
Register and unregister binding objects
You can use the following methods to manage binding objects:
Report a change
You can create the bindable properties in the same way as other data sources, which means that you can also use types as data sources. The main difference between a type and other data sources is that types come with built-in versioning. You must use the built-in versioning of a type to propagate changes.
VisualElementVisualElementVisualElementVisualElementTo report a change, call the method. This method takes a that identifies the property that changed. is typically the name of the target property of the UI element.
NotifyPropertyChangedBindingIdBindingIdThe following example shows how to report a change for a type:
VisualElementpublic 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); } }
Best practices
Follow these tips and best practices to optimize performance:
- Use correct binding IDs: The binding system uses the binding ID to identify the binding object and the target property of the element. The binding ID must be the target property of the element. For example, if you want to bind to the property of a
value, the binding ID must beVector3FieldorVector3Field.valueProperty. In a nutshell, the binding ID must match the name or path of the field or property.value - Avoid internal data updates with bindings: Don't use bindings to update the internal data of a visual element. For example, don't use bindings to synchronize the ,
x, andysub-elements for az. Instead, use a binding to synchronize theVector3Fieldproperty of thevaluewith aVector3Fieldproperty of a data source.Vector3
Known limitations
UI Toolkit doesn't report changes in and . Therefore, you can use binding instances to target the resolved style of an element but can't track changes to them.
element.styleelement.resolvedStyle