Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] CompareConverter - No property, BindableProperty, or event found for "ComparingValue", or mismatching type between value and property #1437

Closed
2 tasks done
MarcosCostaDev opened this issue Oct 2, 2023 · 10 comments · Fixed by #1841
Labels
bug Something isn't working

Comments

@MarcosCostaDev
Copy link

Is there an existing issue for this?

  • I have searched the existing issues

Did you read the "Reporting a bug" section on Contributing file?

Current Behavior

In spite of the comparing value having been set, it is showing a message that it was not set.

Expected Behavior

The expectation is the TrueObject return to the Text Property

Steps To Reproduce

Use the code below to reproduce the issue in any page

Page:

<ContentPage.Resources>
        <ResourceDictionary>
            <toolkit:CompareConverter
                x:Key="SaveButtonTextCompareConverter"
                ComparingValue="0"
                ComparisonOperator="Equal"
                FalseObject="Update"
                TrueObject="Save" />
        </ResourceDictionary>
    </ContentPage.Resources>

<VerticalStackLayout Margin="10,5" Spacing="10">

        <Grid ColumnDefinitions="*, 100" ColumnSpacing="5">
            <Entry Grid.Column="0" Text="{Binding TaskItem}" />
            <Button
                Grid.Column="1"
                Text="{Binding TaskItemId, Converter={StaticResource SaveButtonTextCompareConverter}}" />
        </Grid>
</VerticalStackLayout>

ViewModel

public partial class AnyViewModel : ObservableObject
{

    public TodoViewModel(){}

    [ObservableProperty]
    private int _taskItemId;

Link to public reproduction project repository

https://github.com/MarcosCostaDev/MAUI-sql-server-docker/blob/b1cdbc257396f16715184993f4f2414ec431fb9e/src/TodoMaui/Pages/TodoPage.xaml#L29-L45

Environment

.NET MAUI CommunityToolkit: 6.0.0
OS: Windows 11 Build 10.0.22621
.NET MAUI: 7

Anything else?

No response

@MarcosCostaDev MarcosCostaDev added bug Something isn't working unverified labels Oct 2, 2023
@bijington
Copy link
Contributor

bijington commented Oct 2, 2023

The 0 defined in your XAML is actually a string. You need to follow the approach shown in our sample to achieve what you need:

https://github.com/CommunityToolkit/Maui/blob/main/samples/CommunityToolkit.Maui.Sample/Pages/Converters/CompareConverterPage.xaml#L12

@MarcosCostaDev
Copy link
Author

@bijington Thanks for the response. Your suggestion fixed the issue, Thank you so much!

For reference, this is the way I implemented it:

      <ResourceDictionary>
            <x:Int32 x:Key="ComparingValue">0</x:Int32>
            <toolkit:CompareConverter
                x:Key="SaveButtonTextCompareConverter"
                ComparingValue="{StaticResource ComparingValue}"
                ComparisonOperator="Equal"
                FalseObject="Update"
                TrueObject="Save" />
        </ResourceDictionary>

@hansmbakker
Copy link

hansmbakker commented Apr 17, 2024

@bijington can you please reopen this? It is literally like this in the documentation at https://learn.microsoft.com/en-us/dotnet/communitytoolkit/maui/converters/compare-converter#using-the-compareconverter

image

@bijington
Copy link
Contributor

@hansmbakker I won't reopen this issue but I can open an issue/PR to correct the documentation 👍

@hansmbakker
Copy link

hansmbakker commented Apr 17, 2024

@bijington still - regarding the behavior - I am surprised it doesn't work as it was documented. Given that this issue is about the behavior - could something be done about that?

Having to resort to something like

<ContentPage.Resources>
        <x:Int32 x:Key="one">1</x:Int32>
        <toolkit:CompareConverter
            x:Key="isLargerThanOneConverter"
            ComparingValue="{StaticResource one}"
            ComparisonOperator="Greater"
            FalseObject="{x:Boolean False}"
            TrueObject="{x:Boolean True}" />
</ContentPage.Resources>

really feels awkward, and counter-intuitive. I ran into the same issue because I used it like ComparingValue="1" at first which seemed natural.

@bijington
Copy link
Contributor

@hansmbakker I was surprised too. Sadly this appears to be a limitation of XAML in combination with using the type of the ComparingValue property being an object. This is down to the fact that CompareConverter is a general purpose converter, not designed to cover specifically strongly typed values out of the box.

There are some options though:

Use the approach in your example

I wonder given the values in TrueObject and FalseObject from your sample, firstly does that work? If so then the converter usage could change to:

<ContentPage.Resources>
        <toolkit:CompareConverter
            x:Key="isLargerThanOneConverter"
            ComparingValue="{x:Int32 1}"
            ComparisonOperator="Greater"
            FalseObject="{x:Boolean False}"
            TrueObject="{x:Boolean True}" />
</ContentPage.Resources>

Create a strongly typed converter

Failing that a cleaner although slightly annoying approach would be to subclass the CompareConverter class can create your own strongly typed converter:

public class IntegerCompareConverter : CompareConverter<int>
{
}

And then you can use it as you desire:

<ContentPage.Resources>
        <converters:IntegerCompareConverter
            x:Key="isLargerThanOneConverter"
            ComparingValue="1"
            ComparisonOperator="Greater"
            FalseObject="{x:Boolean False}"
            TrueObject="{x:Boolean True}" />
</ContentPage.Resources>

@hansmbakker
Copy link

@bijington thank you for sharing those hints!

Before posting my second comment I actually tried

<ContentPage.Resources>
        <toolkit:CompareConverter
            x:Key="isLargerThanOneConverter"
            ComparingValue="{x:Int32 1}"
            ComparisonOperator="Greater"
            FalseObject="{x:Boolean False}"
            TrueObject="{x:Boolean True}" />
</ContentPage.Resources>

to avoid the additional x:Int32 StaticResource but got the same compiler error - will try tomorrow again to see if I made a mistake.

Making a specifically-typed subclass could be an option, too.

@bijington
Copy link
Contributor

Although given some limited testing I have done here you might need to combine both of the examples that I mentioned.

I am now wondering whether we could use a TypeConverter to perform some conversion between the supplied value in the XAML and IComparable. My initial attempt has failed miserably but it would be great to simplify the usage.

@bijington bijington reopened this Apr 28, 2024
@bijington
Copy link
Contributor

I said we wouldn't fix this as it wasn't an issue but I have been playing around and will shortly open a PR to show how it can be achieved with a minor structural change to our converter.

@bijington
Copy link
Contributor

@hansmbakker I don't think my examples would have worked without the changes in PR: #1841.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants