xamarin / XamarinCommunityToolkit

The Xamarin Community Toolkit is a collection of Animations, Behaviors, Converters, and Effects for mobile development with Xamarin.Forms. It simplifies and demonstrates common developer tasks building iOS, Android, and UWP apps with Xamarin.Forms.
MIT License
1.59k stars 474 forks source link

[Enhancement] Add ConditionalDoubleConverter #1149

Closed Cfun1 closed 3 years ago

Cfun1 commented 3 years ago

Summary

Add ConditionalDoubleConverter which seem to have similar name as existing IntToBoolConverter but the aim is totally different.

Input is a double and output is a bool, the difference with IntToBoolConverter is that the value of this bool depends on a condition set by the dev, <, >, ==, <=, >=, !=.

API Changes

When ScrollY > 10 returns true otherwise false
<SomeView IsVisible="{Binding ScrollY, Converter={xct:ConditionalDoubleConverter Condition='>', Value=10}"/>

When ScrollY <= 10 returns true otherwise false
<SomeView IsVisible="{Binding ScrollY, Converter={xct:ConditionalDoubleConverter Condition='<=', Value=10}"/>

or better we could extend to more generic than bool like FalseObject TrueObject thing like in BoolToObjectConverter.

When ScrollY > 10 returns blue otherwise red
<SomeView Color="{Binding ScrollY, Converter={xct:ConditionalDoubleConverter Condition='>', Value=10, TrueObject= 'Blue', FalseObject= 'Red'}"/>

if TrueObject and FalseObject are not specified it will return the related bool.

Intended Use Case

A real example could be used to implement a parallax effect, once the scroll value reach a certain threshold you want to set invisible a view.

Who Will Do The Work?

GUOLDEV commented 3 years ago

What about using a ConditionOperator enum?

Cfun1 commented 3 years ago

@GUOLDEV Thanks I didn't know about ConditionOperator, it seems interesting, we'll check what better for this implementation a classic switch statement or ConditionOperator. Is it available out of the box in Xamarin.Forms ?

jBijsterboschNL commented 3 years ago

What about using a ConditionOperator enum?

This ConditionOoerator is part of the Microsoft.Xrm.Sdk namespace, which is used for developing with Microsoft Dynamics. Not sure if you would want to use that one in this scenario.

GUOLDEV commented 3 years ago

Actually, I was thinking about something very simple as the sample code below:

public class CompareConverter : ValueConverterExtension, IValueConverter
{
    enum Conditional
    {
        Equal,
        NotEqual,
        LessThan,
        GreaterThan,
        LessThanOrEqual,
        GreaterThanOrEqual,
    }

    public Conditional? Condition { get; set; }

    public IList<Conditional> Conditions { get; set; } // If you prefer combining enums rather than specific single ones

    public object? ValueToCompare { get; set; }

    public object? Convert(object? value, Type? targetType, object? parameter, CultureInfo? culture)
    {
        if(value is not IComparable c1 || ValueToCompare is not IComparable c2)
            throw new NotSupportedException();

        var result = c1.CompareTo(c2);

        switch (Condition)
        {
            case Conditional.NotEqual:
                return result != 0;
            case Conditional.Equal:
                return result == 0;
            case Conditional.GreaterThan:
                return result > 0;
            case Conditional.LessThan:
                return result < 0;
            default:
                return false;
        }
    }
}
Cfun1 commented 3 years ago

Thanks @GUOLDEV it seems a nice readable approach.

Cfun1 commented 3 years ago

@AndreiMisiukevich what do you think about this feature request ?

GUOLDEV commented 3 years ago

@Cfun1 if the CompareConverter idea is ok and if you don't mind, I am happy to create a PR for this issue.

AndreiMisiukevich commented 3 years ago

CompareConverter sounds good

Cfun1 commented 3 years ago

@GUOLDEV I have already an implementation but I believe we can merge the best of both, I was just waiting for the approval process feedback and thoughts before sending a pr.

pictos commented 3 years ago

@GUOLDEV, @Cfun1 marked this issue as his want to work on it, so I ask you to let him do the implementation. Thanks

GUOLDEV commented 3 years ago

That's great @Cfun1 and thanks for considering merging the ideas, let me know if you need any help 👍

sattew commented 3 years ago

Also I think I can implement it in MathExpressionConverter (#1117)

Cfun1 commented 3 years ago

@sattew I don't think MathExpressionConverter serves the same purpose, this converter will returns a boolean or an object defined by the dev while MathExpressionConverter calculate a math expression and returns the result, IMHO better we don't mix up those two converters. @AndreiMisiukevich @pictos What are your thoughts?

sattew commented 3 years ago

@sattew I don't think MathExpressionConverter serves the same purpose, this converter will returns a boolean or an object defined by the dev while MathExpressionConverter calculate a math expression and returns the result, IMHO better we don't mix up those two converters. @AndreiMisiukevich @pictos What are your thoughts?

Yeah, that is right too. I think MathExpressionConverter can include this logic because the Math includes inequalities. [UP] Ah, MathExpression can compare just digits and it can't be used with IComparable. Maybe we need a new converter.

Cfun1 commented 3 years ago

Implemented in https://github.com/xamarin/XamarinCommunityToolkit/pull/1172