Wiki

Clone wiki

Data Bind / Advanced / Create Your Own Setter

Advanced: Create own Setter

So, you are already familiar with the basic concepts and like/have to write some custom setters, e.g. for a custom UI element? Fortunately this isn't as complicated as it sounds, the plugin was created with easy extensibility in mind.

First of all, check if you can use one of the generic classes in Foundation.Setters as a base class, this would make things much easier:

  • ComponentSingleSetter: If you want to bind a single data value to a property of a single component, you can use this class as a base. You will only have to implement how the data value is used in OnValueChanged. The first type parameter is the type of control target you will manipulate, the second is the type of the data value you need.
  • SingleSetter: Most of the time you want to bind a single data value. If that's the case this class comes in handy. You will only have to implement how the data value is used in OnValueChanged.
  • Setter: Most basic class which provides methods to add/remove data bindings. You should at least use this class as a base class to make sure that your setter behaves correctly when the context changes.

As an example, here's the whole code used to implement the TextTextSetter:

#!c#

namespace Slash.Unity.DataBind.UI.Unity.Setters
{
    using Slash.Unity.DataBind.Foundation.Setters;

    using UnityEngine;
    using UnityEngine.UI;

    /// <summary>
    ///   Set the text of a Text depending on the string data value.
    /// </summary>
    [AddComponentMenu("Data Bind/UnityUI/Setters/[DB] Text Text Setter (Unity)")]
    public class TextTextSetter : ComponentSingleSetter<Text, string>
    {
        #region Methods

        protected override void OnValueChanged(string newValue)
        {
            if (this.Target != null)
            {
                this.Target.text = newValue;
            }
        }

        #endregion
    }
}

Really easy, isn't it?

Let's have a look how to implement a setter using only the most basic class Setter. We have to provide two things:

  • One or more data bindings where the user can specify where the data comes from he wants to set
  • One or more targets where the provided data should be set

    public class TwoTextSetter : Slash.Unity.DataBind.Foundation.Setters.Setter { }

For the data bindings we use the class DataBinding as fields. Let's say we have two data values that our setter requires to work, so we provide two DataBinding fields:

public Slash.Unity.DataBind.Core.Presentation.DataBinding Data1;

public Slash.Unity.DataBind.Core.Presentation.DataBinding Data2;

Now our setter takes those two values and uses them to manipulate, mmmh, let's say a Text. So we need a reference to this text:

public UnityEngine.UI.Text Target;

Okay, we've got the basics in place. If we assign our setter to a game object we can already set it up, defining were the data is coming from and which label to manipulate. But nothing is happening with the data, yet. Let's change this by letting our setter know when the data changes:

#!c#
protected void Awake()
{
    this.AddBinding(this.Data1);
    this.AddBinding(this.Data2);
}

protected void OnDestroy()
{
    this.RemoveBinding(this.Data1);
    this.RemoveBinding(this.Data2);
}

protected void OnDisable()
{
    this.Data1.ValueChanged -= this.OnValueChanged;
    this.Data2.ValueChanged -= this.OnValueChanged;
}

protected void OnEnable()
{
    this.Data1.ValueChanged += this.OnValueChanged;
    this.Data2.ValueChanged += this.OnValueChanged;
}

We use the Unity methods Awake/OnDestroy to add/remove our data bindings, so they are correctly initialized and react on context changes. The methods OnEnable/OnDisable are used to register the setter for value changes of the data bindings. In that case the method OnValueChanged is called:

#!c#
private void OnValueChanged(object newValue)
{
    if (this.Target != null)
    {
        this.Target.text = this.Data1.Value + " AND " + this.Data2.Value;
    }
}   

What we do in OnValueChanged is to concatenate the two data values and assign the string as the text of the label. Nothing super special and could also be achieved by a TextTextSetter and a StringFormatter, but it shows the point, I hope.

Here's how your setter will look like in Unity:

12058648.png

And basically that's it. The logic you do in OnValueChanged with the data values is the main part of a setter, but most of the time doesn't involve much more than setting the right property on the target element (if it does, you should consider moving it into an own Formatter).

Updated