XamlC resolves x:DataType incorrectly
mattleibow opened this issue ยท 14 comments
Description
This is partly a collection of issues and partly a more specific issue. Not sure if this is 100% a bug in all cases either.
XamlC uses the x:DataType="<type-name>"
on <DataTemplate>
to generate type-specific bindings, however, somce times the scope is incorrect or if the XAML is wrong but happens to match there is no exception and just fails silently.
In debug you can also get these errors using
<_MauiForceXamlCForDebug>true</_MauiForceXamlCForDebug>
but still no warnings or exceptions anywhere.
Steps to Reproduce
- Clone https://github.com/mattleibow/maui-bug-repros/tree/repro-xamlc-datatype
- Run
- Observe that not all the collection views have items in them
Link to public reproduction project repository
https://github.com/mattleibow/maui-bug-repros/blob/repro-xamlc-datatype/MauiApp1/MainPage.xaml
Version with bug
7.0 (current)
Last version that worked well
Unknown/Other
Affected platforms
iOS, Android, Windows, macOS, Other (Tizen, Linux, etc. not supported by Microsoft directly)
Affected platform versions
All versions
Did you find any workaround?
Make sure the x:DataType
is specified correctly, and on every level of templates.
Relevant log output
No response
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.
@StephaneDelcroix thoughts?
This may have a simpler repro case: #13764
Can you give some love (priority) to this issue (I created a duplicated one yesterday the one @mattleibow mentioned) ?
From what I see Compiled bindings don't actually work as compiled bindings in MAUI and this issue is 3 months old
Thanks
Bump
Bump
Bump
Trying to keep the issue alive :)
Verified this issue with Visual Studio Enterprise 17.7.0 Preview 3.0(net8). Can repro on Windows platform with sample Project.
https://github.com/mattleibow/maui-bug-repros/tree/repro-xamlc-datatype
@StephaneDelcroix Can I add this one to your short list?
I can reproduce the issue with a Button
in a CollectionView
DataTemplate
that binds to a Command on the page's BindingContext
and passes the data binding element {Binding .}
to it as a parameter
my comment and repro from #13754 (comment)
still a critical issue with version 8.0.0-preview.7.8842 which completely breaks
CollectionView
(haven't tested with other collection controls) on Windows. I have the usecase of aButton
inside aCollectionView
that has aCommand
binding to theViewModel
and passes the current Item (MyItem
class) as aCommandParameter
.Executing this command fails of course because the Type of the
CommandParameter
isViewModel
instead ofMyItem
Error Message:
Parameter "parameter" (object) cannot be of type MauiApp1.MainViewModel, as the command type requires an argument of type MauiApp1.MyItem. (Parameter 'parameter')
StackTrace:
at CommunityToolkit.Mvvm.Input.RelayCommand`1.ThrowArgumentExceptionForInvalidCommandArgument(Object parameter) at CommunityToolkit.Mvvm.Input.RelayCommand`1.Execute(Object parameter) at Microsoft.Maui.Controls.ButtonElement.ElementClicked(VisualElement visualElement, IButtonElement ButtonElementManager) at Microsoft.Maui.Controls.Button.SendClicked() at Microsoft.Maui.Controls.Button.Microsoft.Maui.IButton.Clicked() at Microsoft.Maui.Handlers.ButtonHandler.OnClick(Object sender, RoutedEventArgs e) at WinRT._EventSource_global__Microsoft_UI_Xaml_RoutedEventHandler.EventState.<GetEventInvoke>b__1_0(Object sender, RoutedEventArgs e) at ABI.Microsoft.UI.Xaml.RoutedEventHandler.Do_Abi_Invoke(IntPtr thisPtr, IntPtr sender, IntPtr e) --- End of stack trace from previous location --- at WinRT.ExceptionHelpers.<ThrowExceptionForHR>g__Throw|20_0(Int32 hr) at WinRT.ExceptionHelpers.ThrowExceptionForHR(Int32 hr) at ABI.Microsoft.UI.Xaml.Controls.IControlOverridesMethods.OnPointerReleased(IObjectReference _obj, PointerRoutedEventArgs e) at Microsoft.UI.Xaml.Controls.Control.OnPointerReleased(PointerRoutedEventArgs e) at Microsoft.UI.Xaml.Controls.Control.Microsoft.UI.Xaml.Controls.IControlOverrides.OnPointerReleased(PointerRoutedEventArgs e) at ABI.Microsoft.UI.Xaml.Controls.IControlOverrides.Do_Abi_OnPointerReleased_3(IntPtr thisPtr, IntPtr e)
And of course the output log is filled with Binding Diagnostic Errors:
Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: 'ClickCommand' property not found on 'MauiApp1.MainViewModel', target property: 'Microsoft.Maui.Controls.Button.Command' Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: 'Name' property not found on 'MauiApp1.MainViewModel', target property: 'Microsoft.Maui.Controls.Label.Text' Microsoft.Maui.Controls.Xaml.Diagnostics.BindingDiagnostics: Warning: 'Description' property not found on 'MauiApp1.MainViewModel', target property: 'Microsoft.Maui.Controls.Label.Text'
My Repro:
I wrote a test for 13764 and it looks like this no longer happens (main branch). The observer behavior is as follow
- on Debug, x:DataType is ignored, and binding are resolved if possible using reflection
- on Release, bindings with the wrong x:DataType silently fail
making the page crash on mismatching DataType is NOT an option, as the binding context could change multiple times when parenting the element until the 'right' context is set
what are the expectation ? sending a binding diagnostic warning on Debug ?
I suppose I lumped them all in together because I suppose I expected an exception. But maybe these are 3 separate issues and one is "just add a message".
Probably this one is more we need to add some logging or maybe a way to detect this. The generated code is using the type in the XAML, and thus it does not work. Maybe a detection can be added or logs:
<!--
This results in an incorrect UI because the DataType on the
DataTemplate is the wrong one.
The generated TypedBinding is using the "incorrect" types:
TypedBinding<SubItem, string>
-->
<Label Text="Incorrect binding, an incorrect DataType:" />
<CollectionView ItemsSource="{Binding Items}" HeightRequest="100">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:SubItem">
<Label Text="{Binding Name}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
This one feels more actionable somehow because of a missing DataType, the inner layer is using the outer type. In this case, the ItemsSource is always (maybe) going to change the binding context of the items. Should there be a way to say that we are using a DataType on an outer layer, so "reset" the type for the inner CV?
<!--
This results in an incorrect UI because there is no DataType on the
DataTemplate and XamlC falls back to the DataType on the one above.
The generated TypedBinding is using the incorrect types:
TypedBinding<CollectionItem, string>
-->
<Label Text="Incorrect nested binding, parent DataType:" />
<CollectionView ItemsSource="{Binding Items}" HeightRequest="100">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:CollectionItem">
<CollectionView ItemsSource="{Binding SubItems}" HeightRequest="100">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Name}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
This is probably a user error, but I have seen it happen a lot in samples. The DataType attribute is on the ItemTemplate property... shomehow... so should this be a XAMLC error as there is no way to do this in reality?
<!--
This results in an incorrect UI because the DataType is not on the
DataTemplate so is ignored.
The generated TypedBinding is using the incorrect types:
TypedBinding<CollectionItem, string>
-->
<Label Text="Incorrect nested binding, parent DataType:" />
<CollectionView ItemsSource="{Binding Items}" HeightRequest="100">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="local:CollectionItem">
<CollectionView ItemsSource="{Binding SubItems}" HeightRequest="100">
<CollectionView.ItemTemplate x:DataType="local:SubItem">
<DataTemplate>
<Label Text="{Binding Name}" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
@mattleibow I created this PR that will warn if there's a Binding that inherits the x:DataType
from outside of its DataTemplate
scope: #22803 Would that resolve this issue?