dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22k stars 1.72k forks source link

XamlC: IValueConverter with generic arguments cannot process GridLength #10255

Open Kiitoksia opened 1 year ago

Kiitoksia commented 1 year ago

Description

If type arguments for a converter uses GridLength, then the XAMLC parser returns an error and the project does not build. Using the class shown here https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/converters#binding-converter-properties

Then assign it to a ContentPage.

<ContentPage.Resources>
        <t:BoolToObjectConverter x:Key="FailedConverter" x:TypeArguments="GridLength" TrueObject="*" FalseObject="80"/>
        <t:BoolToObjectConverter x:Key="WorkingConverter" x:TypeArguments="x:Int32" TrueObject="10" FalseObject="80"/>
</ContentPage.Resources>

Upon adding it into a a ContentPage and assigning, this error appears.

XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.

The same approach builds and works fine in Xamarin.Forms.

Steps to Reproduce

  1. Create a file > New .NET MAUI App
  2. Create the BoolToObjectConverter class, directly copied from https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/data-binding/converters#binding-converter-properties
  3. Add New Item > .NET MAUI Content Page (XAML)
  4. Create two instances of the BoolToObjectConverter, one for an Int, and one for GridLength

Expected outcome: Both converters work and the project builds Actual outcome: Converter with GridLength type arguments fails to build with XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.

Link to public reproduction project repository

https://github.com/Kiitoksia/MAUIValueConverterGridLength

Version with bug

6.0.486 (current)

Last version that worked well

Unknown/Other

Affected platforms

iOS, Android

Affected platform versions

All

Did you find any workaround?

No workaround found other than continuing to use Xamarin.Forms where this functionality works.

Relevant log output

1>TestPage.xaml(8,87): XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.
1>TestPage.xaml(8,87): XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.
1>TestPage.xaml(8,87): XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.
1>TestPage.xaml(8,87): XamlC error XFC0009: No property, BindableProperty, or event found for "TrueObject", or mismatching type between value and property.
ghost commented 1 year ago

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

PureWeen commented 1 year ago

@StephaneDelcroix thoughts?

Zhanglirong-Winnie commented 1 year ago

Verified this issue with Visual Studio Enterprise 17.7.0 Preview 3.0(net8). Can repro on android platform with sample project. MAUIValue.zip Screenshot 2023-07-17 175244

thomasgalliker commented 1 year ago

I just experienced the same issue. It happens with the following, very simple converter:

public class BoolToGridLengthConverter : BindableObject, IValueConverter
    {
        public static readonly BindableProperty TrueValueProperty = BindableProperty.Create(nameof(TrueValue), typeof(GridLength), typeof(BoolToGridLengthConverter), default(GridLength));
        public static readonly BindableProperty FalseValueProperty = BindableProperty.Create(nameof(FalseValue), typeof(GridLength), typeof(BoolToGridLengthConverter), default(GridLength));

        public GridLength TrueValue
        {
            get => (GridLength)GetValue(TrueValueProperty);
            set => SetValue(TrueValueProperty, value);
        }

        public GridLength FalseValue
        {
            get => (GridLength)GetValue(FalseValueProperty);
            set => SetValue(FalseValueProperty, value);
        }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var obj = FalseValue;
            if (value is bool b)
                obj = b ? TrueValue : FalseValue;

            return obj;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Use case:

<converters:BoolToGridLengthConverter
    x:Key="BoolToGridLengthStarConverter"
    TrueValue="*"
    FalseValue="0" />

It might not help very much, but the same converter used to work fine in Xamarin.Forms. Thanks for your effort!

pandaloupe commented 10 months ago

I made it work by using string as datatype for the properties. It's not what you really want but it might help until the issue is fixed (if ever). `public class GridLengthConverter : BindableObject, IValueConverter { public static readonly BindableProperty TrueLengthProperty = BindableProperty.Create(nameof(TrueLength), typeof(string), typeof(GridLengthConverter)); public static readonly BindableProperty FalseLengthProperty = BindableProperty.Create(nameof(FalseLength), typeof(string), typeof(GridLengthConverter));

public string TrueLength
{
    get => (string)GetValue(TrueLengthProperty);
    set => SetValue(TrueLengthProperty, value);
}

public string FalseLength
{
    get => (string)GetValue(FalseLengthProperty);
    set => SetValue(FalseLengthProperty, value);
}

public GridLengthConverter()
{
    TrueLength = "Auto";
    FalseLength = "0";
}

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if ((bool) value == true)
    {
        return GetGridLength(TrueLength);
    }

    return GetGridLength(FalseLength);

}

private GridLength GetGridLength(string length)
{
    switch (length)
    {
        case "Auto":
            return GridLength.Auto;
        case "*":
            return GridLength.Star;
        default:
            return new GridLength(double.Parse(length));
    }
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}

}`

thomasgalliker commented 10 months ago

@pandaloupe yeah, 1:1 what we did as a workaround 😅👍🏻 I still hope the maui team gets this fixed. Thanks for posting!

Perksey commented 9 months ago

Just hit this one today as well, what an odd case!

JayMansel commented 7 months ago

Just adding my 2 cents. We have the same issue here but with a custom control with a BindableProperty of type GridLength. During compilation, we get the above XFC0009 error, when we try to set the value to '*' or 'Auto', or a literal value.

dfyx commented 2 weeks ago

Had the same problem with a custom control, here's a different workaround:

<controls:PageSection>
    <controls:PageSection.IconWidth>
        <sytem:Double>40</system:Double>
    </controls:PageSection.IconWidth>
    <!-- Other properties and content -->
</controls:PageSection>

While strings can't be converted, doubles can. For * and Auto, use {x:Static GridLength.Star} and {x:Static GridLength.Auto}