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

[MAUI] Specified cast is not valid #38

Open
Alex-Dobrynin opened this issue Jul 9, 2024 · 5 comments
Open

[MAUI] Specified cast is not valid #38

Alex-Dobrynin opened this issue Jul 9, 2024 · 5 comments

Comments

@Alex-Dobrynin
Copy link

If I try to add x:Bind to an object which is not Element but only BindableObject I'm getting the exception specified in the title. If I use regular Binding, then it works as expected.

For example I have

public class Pin : BindableObject
{
    // Assume this is BindableProperty
    public string Address { get; set; }
}

And if I do in XAML smth like this

<Pin Address="{x:Bind SomeProperty}" />

I'm getting 'Specified cast is not valid'

@levitali
Copy link
Owner

Can you provide a sample project?

Because Pin class is not a view, you can set it XAML only to some property.

I have a custom View ContentControl with DataContent property of type object. When I set it like this:

<local:ContentControl>
    <local:ContentControl.DataContent>
        <local:Pin Address="{x:Bind SomeProperty}" />
    </local:ContentControl.DataContent>
</local:ContentControl>

it works.

@Alex-Dobrynin
Copy link
Author

Alex-Dobrynin commented Jul 10, 2024

I'm just using Maui.GoogleMaps. and it does have Map control, which has ItemsSource. Also it has ItemTemplate, which expects DataTemplate be typeof(Pin), where Pin is BindaleObject. and when I'm trying to do x:Bind inside this DataTemplate I'm getting the error I mentioned in the title

<googlemaps:Map ItemsSource="{x:Bind Pins}">
    <googlemaps:Map.ItemTemplate>
        <DataTemplate x:DataType="googlemaps:Pin">
            <googlemaps:Pin Position="{x:Bind Position}" />
        </DataTemplate>
    </googlemaps:Map.ItemTemplate>
</googlemaps:Map>

As you can see, the DataType for DataTemplate also typeof(Pin)

@levitali
Copy link
Owner

Data Templates should only be used to specify appearance of a data item. Look at documentation.

A DataTemplate is used to specify the appearance of data

Because of this, generated code expects, that content of a DataTemplate is derivied from Element:

static void BindingsChanged(global::Microsoft.Maui.Controls.BindableObject bindable, object oldValue, object newValue)
{
	if (oldValue != null)
	{
		((IGeneratedDataTemplate)oldValue).Cleanup((global::Microsoft.Maui.Controls.Element)bindable);
	}
	if (newValue != null)
	{
		((IGeneratedDataTemplate)newValue).Initialize((global::Microsoft.Maui.Controls.Element)bindable);
	}
}

Also Visual Studio displays a warning because of misused DataTemplate:

Untitled

I've looked at the code of the Map control, which is also developed by you. I don't quite understand the need of ItemsSource and ItemTemplate properties. The pins can be created and added directly to Pins property. Or it can be settable.

@Alex-Dobrynin
Copy link
Author

The code wasn't developed by me. I just did PR with another changes to it. But the original implementation is from Xamarin.Forms.GoogleMaps. The package Maui.GoogleMaps is migrated version for XF one by @themronion. Why it was made so I don't know. but it is working even with that warning you showed in the picture.

But. maybe you can change the implementation of generated code to expect BindableObject instead of Element?

@levitali
Copy link
Owner

It involves many changes. The code, generated for a DataTemplate, needs that the root object is an Element.

Maybe I will do it in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants