In the first part I talked about the basics of data binding, namely the data context and the data property, which define the data that is provided from the logic for the presentation side of your game. This makes it possible to visualize the data and react on data changes.
One part is missing though: Giving the presentation side a possibility to send desired actions into the logic, e.g. when the user clicks on a button. This feature is implemented by commands.
How to use commands
First let’s go to our data context another time. Here we can define which actions are available to be called by the presentation side by defining public void methods:
public void SubmitMessage(string text)
// Your code here
You can use as many parameters as you like, but the command on the presentation side we create later has to provide these parameters, of course. Most of the time you won’t need any or only one.
Creating the UI and making the connection
Now that we know which actions the data context supports, we can create an interface which let’s the user call those actions. In our example we could use an input field where the user types in his message and a button with which he can send it.
You are free to create a much fancier user interface then mine, of course 😉 But the interface itself won’t do much on its own, so let’s create the connection to the data context. This is where our commands come into play.
What we want to do is call the SubmitMessage method with the text of the input field as the parameter. Data Bind for Unity already contains a bunch of predefined commands, so we can just use the ButtonClickCommand by adding the component to our button and choosing the path to the method we like to invoke on a click.
If there weren’t any parameters to the command, we would be already done. But as we don’t go the easy way, we have to provide an additional parameter for the command, otherwise it won’t work.
Providing command parameters
As we said earlier we like to send the content of the input field as a parameter when the button is clicked. Therefore we need a way to grab the text from the input field. Luckily the InputFieldGetter script does this job for us. Getters in Data Bind have two functions:
- Update a data property when a value on presentation side changed, e.g. for input fields, sliders, toggles,…
- Provide a generic data interface for commands and other bindings
All Getters derive from the DataProvider class. This mono behaviour manages a single data value, quite similar to a data property. Other bindings can use the value and are informed when it changes.
Back to our ButtonClickCommand : The base Command class has a member called AdditionalArguments where we can reference any number of data providers. In our case we need only one, the InputFieldGetter we put on our input field. We can just drag the input field on the additional arguments list and the connection is made.
If we click the button in our game now, the current value of the provided data provider is send as a parameter to our SubmitMessage method.
Behind the scenes
So what’s happening exactly? As you learned in part 1 there are three method the Context class provides:
- object RegisterListener(string path, Action<object> onValueChanged)
- void RemoveListener(string path, Action<object> onValueChanged)
- void SetValue(string path, object value)
For our commands we use the first two, so it is not much different to register a listener for a data value. Besides we register for a method instead of a field or a property. If a path in a data context points to a method, a delegate is returned as the value of this path.
If the command detects its trigger, e.g. a button click, it uses this delegate to invoke the method on the data context and passes the additional arguments as parameters. It’s important that the number and type of the parameters match, otherwise the invocation won’t be successful.
A more detailed example of the command usage is included in the Data Bind for Unity asset, called InputFieldGetterExample. You may just dive in there if you like to see it working. If you have any detailed questions about commands, just write a comment or contact me.
Some more details about data nodes
When I read through part 1 once more, I realized that it may not have become clear how the context base class works exactly when providing the data values to the bindings.
Just think about the context as a data tree. The root node is the context itself and each node can have children on its own.
When RegisterListener is called with a path, the context traverses this tree with the parts of the path and registers the callback at the found node.
If a value in the tree changes, the callbacks on this node are called. Furthermore the children of the node are updated as well as they may have changed by this data change, too. This way one can easily register itself for a data property of a sub context and is also informed if the whole sub context changes.
So the data nodes are really just another representation of the data provided by the context which contain additional meta information about each node for fast access and management of the callbacks from the bindings.
Part 2 summary
Good thing I split up the post, it would have been far to much for a single one. In this part you got some insights about:
- How to define the actions in the data context
- How to add them on the UI side
- How to provide additional parameters for a command
- How they work
- Data nodes
- How they look like
- What they are good for
There are many more details about how the Data Bind asset works, but for now this should be enough to understand the basics. If you are interested in learning more, check out the documentation and the API. Let me know if a topic is of particular interest for you, then I’ll consider to write another post about it.
Our asset got its second update yesterday and its functionality grew quite a bit. As it was planned, I’ll raise the price for it with the next update soon, so be smart and grab it while it’s still 10$ if you haven’t already 🙂
Thanks for your time reading my stuff, hope you enjoyed it!