Hello, this feels like a very simple problem to which there should be an appropriately simple solution using UI toolkit, but I have found that not to be the case.
I have a data model with a boolean value. I want to bind the display
property of a visual element to this value, where true -> flex
, false -> none
. I tried using a converter for this, based off one of the example in the documentation:
var group = new ConverterGroup("Bool Converters");
group.AddConverter((ref bool value) =>
{
return value ? DisplayStyle.Flex : DisplayStyle.None;
});
ConverterGroups.RegisterConverterGroup(group);
However this just straight up doesn’t work - I can select the source variable and the converter group in the data binding UI, but Unity complains about the types being incompatible, and it doesn’t do anything at runtime:
The only solution I’ve found is to define a new variable which is the literal DisplayStyle, and toggle it every time the underlying boolean changes, i.e.,
public DisplayStyle ThingDisplayStyle = DisplayStyle.Flex
But this is a really unsatisfactory solution that basically eliminates the advantage of binding to begin with. If I could at least bind to a function based off the underlying data that would be a marked improvement, but that does not work either:
public DisplayStyle ThingDisplayStyle() { // can't bind to functions :(
return MyBool? DisplayStyle.Flex : DisplayStyle.None;
}
If you have any ideas on how to do this more elegantly, please let me know!
Hi @JamesPriebe,
Converters need to match the destination type exactly, which in your case is not a DisplayStyle
, but a StyleEnum<DisplayStyle>
. If you return a StyleEnum<DisplayStyle>
from your converter, then in that case, it should work.
If you plan on using that converter all the time, you can also register it as a global converter and it will be used any time you want to convert from a bool
to a StyleEnum<DisplayStyle>
.
Hope this helps!
2 Likes
Thanks @martinpa_unity , that worked! Regarding global converters - I’m a bit confused on how/where they’re meant to be initialized… should I just stick them in some class and have register them on load? e.g.,
public class UI_Converters
{
#if UNITY_EDITOR
[InitializeOnLoadMethod]
#else
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
#endif
public static void RegisterConverters()
{
ConverterGroups.RegisterGlobalConverter(
(ref bool value) =>
{
return (StyleEnum<DisplayStyle>)(value ? DisplayStyle.Flex : DisplayStyle.None);
}
);
}
}
And then any such converters will “just work” and apply automatically to matching source/destination types?
Yep, that is the idea, once a converter is registered globally, it will be used when any bool
to StyleEnum<Display>
is needed, provided a converter with the same types has not been registered on the binding directly.
Note that converters registered on a binding directly can have one converter when binding to UI and another converter when binding back to the data source. In that regard, global converters will be used in both direction.
Hope this helps!