Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum support in MvvmCross data-binding

Tags:

mvvmcross

I have an enum property in the view-model and I want to make a label visible if the property value is of a specific value

States state;
public States State
{
    get { return this.state; }
    set
    {
        if (this.state != value)
        {
            this.state = value;
            this.RaisePropertyChanged("State");
        }
    }
}

public enum States
{
    Stopped,
    Runnning
}

here's what I tried in the UI:

local:MvxBind="Visibility If(State==1, 'Visible', 'Gone')"

but it doesn't work. No error is displayed in the log.

I can make a converter but I was wondering if it's possible to do it without it.

If I modify the State property to use int instead of Enum, it works fine. I guess it has to do with how currently Enum type is handled.

like image 798
WriteEatSleepRepeat Avatar asked Feb 19 '26 03:02

WriteEatSleepRepeat


1 Answers

In the Tibet binding addons, statements like:

 If(State==1, 'Visible', 'Gone'

are not compiled because of iOS JIT limitations - instead they are evaluated.

Sadly the evaluation of operators like == turned out to be quite difficult to do without using dynamic code...

Because of this, what the Tibet == operator tries to do is to reduce the right and left sides down to one of three types: long, double or object - it does this using:

    private Type GetLookupTypeFor(object value)
    {
        if (value == null)
            return null;
        if (value is long)
            return typeof(long);
        if (value is double)
            return typeof (double);
        return typeof (object);
    }

from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding/Combiners/MvxPairwiseValueCombiner.cs#L36

with these types determined it then calls one of these methods, each of which uses the == operator of the left-hand type or .Equals if both types are object:

    protected override bool CombineDoubleAndDouble(double input1, double input2, out object value)
    {
        value = input1 == input2;
        return true;
    }
    protected override bool CombineDoubleAndLong(double input1, long input2, out object value)
    {
        value = input1 == input2;
        return true;
    }
    // ... etc

from https://github.com/MvvmCross/MvvmCross/blob/v3.1/Cirrious/Cirrious.MvvmCross.Binding/Combiners/VeryExperimental/MvxEqualToValueCombiner.cs

For the enum case of State==1, I think the left-hand will be identified as an object and the right-hand as a long - so these will never be equal because of:

    protected override bool CombineObjectAndLong(object input1, long input2, out object value)
    {
        value = false;
        return true;
    }

Working with the current code, I think the only way to get the test to work is to get both left and right-side to long or to string.

You could do that using a value converter on the enum - e.g. a ToStringValueConverter or a ToLongValueConverter which you could then use like:

 If(ToLong(State)==1, 'Visible', 'Gone'

or:

 If(ToString(State)=='Running', 'Visible', 'Gone'

Obviously, looking forwards, this area could also be improved inside Mvx - in whatever lies beyond Swiss and Tibet

like image 199
Stuart Avatar answered Feb 21 '26 13:02

Stuart



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!