maui icon indicating copy to clipboard operation
maui copied to clipboard

XAML bindings are flagging invalid binding failures in ListView - it is confused as to what the data context is...

Open mobycorp opened this issue 3 years ago • 31 comments

Description

I have a list view which has its items source set to an observable collection in a top-level view model. The collection is a list of detail view models. I have explicitly set the data context in the item template to point to the detail view model, yet the error it flags indicates it is looking at the page's data context and not the context of a single element in the list. I hate to see any binding failures, but this one will not go away...

Here is the binding error listed (there are three, actually):

Data Context	EmailsViewModel
Binding Path	Email
Target		Label.Text
Target Type	String
Description	'Email' property not found on 'MobyClient.ViewModels.EmailsViewModel', target property: 'Microsoft.Maui.Controls.Label.Text'
File			\Pages\PageEmails.xaml
Line			268

Here is the EmailsViewModel class:

namespace MobyClient.ViewModels;

public partial class EmailsViewModel : ObservableObject {

	public EmailsViewModel (IMobyLogger logger, EmailService emailService) {

		Guard.IsNotNull (logger);
		Guard.IsNotNull (emailService);

		_logger = logger;
		_emailService = emailService;
	}

	public ObservableCollection<EmailViewModel> FilteredEmails { get; set; }
	public ObservableCollection<FolderViewModel> Folders { get; set; }

	private void InitializeViewModel () {
		if (_isInitialized) return;

		_filteredEmails = new List<Email> (_emailService.Emails);

		FilteredEmails = new ObservableCollection<EmailViewModel> ();
		Folders = new ObservableCollection<FolderViewModel> (_emailService.Folders);

		_logger.LogDebug ("Emails viewmodel is initialized.");

		_isInitialized = true;
	}

	private bool _isInitialized;
	private List<Email> _filteredEmails;
	private readonly IMobyLogger _logger;
	private readonly EmailService _emailService;
}

And here is the EmailViewModel:

namespace MobyClient.ViewModels;

public partial class EmailViewModel : ObservableObject {

	[ObservableProperty]
	private Email _email;
}

Looking at the xaml used to define the list view item template:

<ListView.ItemTemplate>
	<DataTemplate>
		<ViewCell>
			<Grid
				Margin="0,1,0,0"
				Padding="3,0">
				<Grid
					x:Name="FolderItemTemplateGrid"
					x:DataType="viewModels:EmailViewModel"
					ColumnDefinitions="Auto, *, Auto"
					ColumnSpacing="5"
					Margin="10,2"
					ZIndex="1000">
					<Label
						Grid.Column="0"
						FontFamily="SegoeUiRegular"
						FontSize="14"
						Text="{Binding Email.SenderEmail.ShortDisplayName}" />
					<Label
						Grid.Column="1"
						FontFamily="SegoeUiRegular"
						FontSize="14"
						Margin="10,0,0,0"
						MaximumWidthRequest="1000"
						Text="{Binding Email.Subject}" />
					<Label
						Grid.Column="2"
						FontFamily="SegoeUiRegular"
						FontSize="14"
						Margin="10,0,0,0"
						Text="{Binding Email.MessageDate}" />
				</Grid>
			</Grid>
		</ViewCell>
	</DataTemplate>
</ListView.ItemTemplate>

I am clearly setting the datatype for the item template to be of the EMAIL view model and NOT the EMAILS view model! Trust me when I say that the Email class DOES have the properties, SenderEmail.ShortName (from an EmailAddress class), Email.Subject, and Email.Message date.

So, why is the error pointing to the EmailsViewModel when I have set the datatype to be EmailViewModel? Intellisense works (which to my understanding is driven by the x:DataType property... I don't get it!

My code base has grown to a size where it is not feasible to give you a github repository, so the code snippets above will have to work.

Steps to Reproduce

I know you won't like this, but you will need to generate a simple app that has a listview with an itemtemplate defined as I listed above.

I can see no reason why these binding errors are being flagged....

Version with bug

6.0.400 (current)

Last version that worked well

Unknown/Other

Affected platforms

Windows, I was not able test on other platforms

Affected platform versions

net6.0-windows10.0.19041.0

Did you find any workaround?

No...

Relevant log output

No response

mobycorp avatar Jun 29 '22 20:06 mobycorp

Hi, @mobycorp - Thank you for opening this issue. I understand that you may not be able to share your project, but would you be able to share a sample (in the form of a GitHub repository) that reproduces the issue you describe? That would help us tremendously in investigating this further and helping to debug this issue.

rachelkang avatar Jun 30 '22 00:06 rachelkang

Hi @mobycorp. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jun 30 '22 00:06 ghost

I am currently on a severe deadline and barely have time to eat dinner, so, no. I cannot supply you with example code. I indicated as much from above. You guys are smart guys and should have no problem reproducing what I have reported.

mobycorp avatar Jun 30 '22 00:06 mobycorp

@mobycorp

  • do you get that error at runtime or compile time
  • running in DEBUG or RELEASE. does it happens on both ?
  • how are you setting your list view item source
  • are you sure EmailViewModel has a public Email property ?

We tried to come up with a repro, based on the scarce info you gave us, but that repro is working well. I'm sorry about your severe deadlines, and the impact on your work-life balance. We understand the sense of urgency, and this is why you got quick answers. If you really need this investigated, you definitely have to provide the smallest possible project that triggers this behaviour, and we will look at it. Thanks

StephaneDelcroix avatar Jun 30 '22 08:06 StephaneDelcroix

Hi @mobycorp. We have added the "s/needs-repro" label to this issue, which indicates that we require steps and sample code to reproduce the issue before we can take further action. Please try to create a minimal sample project/solution or code samples which reproduce the issue, ideally as a GitHub repo that we can clone. See more details about creating repros here: https://github.com/dotnet/maui/blob/main/.github/repro.md

This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jun 30 '22 08:06 ghost

Untitled

I'm not trying to be difficult. I am on a tight deadline... And, Gerald, love your YouTube channel!! :-)

The errors are triggered by the display of content in the listview in the picture. One per row x3 because there are three properties in the view model. I tried dereferencing the three properties so that:

<Grid
	x:Name="FolderItemTemplateGrid"
	ColumnDefinitions="Auto, *, Auto"
	ColumnSpacing="5"
	Margin="10,2"
	ZIndex="1000">
	<Label
		Grid.Column="0"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Text="{Binding Email.SenderEmail.ShortDisplayName}" />
	<Label
		Grid.Column="1"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Margin="10,0,0,0"
		MaximumWidthRequest="1000"
		Text="{Binding Email.Subject}" />
	<Label
		Grid.Column="2"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Margin="10,0,0,0"
		Text="{Binding Email.MessageDate}" />
</Grid>

becomes:

<Grid
	x:Name="FolderItemTemplateGrid"
	ColumnDefinitions="Auto, *, Auto"
	ColumnSpacing="5"
	Margin="10,2"
	ZIndex="1000">
	<Label
		Grid.Column="0"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Text="{Binding ShortDisplayName}" />
	<Label
		Grid.Column="1"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Margin="10,0,0,0"
		MaximumWidthRequest="1000"
		Text="{Binding Subject}" />
	<Label
		Grid.Column="2"
		FontFamily="SegoeUiRegular"
		FontSize="14"
		Margin="10,0,0,0"
		Text="{Binding MessageDate}" />
</Grid>

but this did not change anything. The errors are still being generated...

@jfversluis, since I you didn't post the xaml you used to generate your example picture, I am not sure if you are doing things exactly like me. Did you create an item template that looks similar to the above. I know that HotReload NEVER works when I makes changes to code in a template and I am wondering if it is because of the item template... ???

This is my entire listview definition:

<ListView
	ItemsSource="{Binding FilteredEmails}"
	SelectionMode="Single">
	<ListView.ItemTemplate>
		<DataTemplate
			x:DataType="viewModels:EmailViewModel">
			<ViewCell>
				<Grid
					Margin="0,1,0,0"
					Padding="3,0">
					<Grid.GestureRecognizers>
						<TapGestureRecognizer
							Command="{Binding EmailSelectedCommand, Source={RelativeSource AncestorType={x:Type viewModels:EmailsViewModel}}}"
							CommandParameter="{Binding}" />
					</Grid.GestureRecognizers>
					<Rectangle
						BackgroundColor="{StaticResource Gray100}"
						Stroke="Gray"
						StrokeThickness="1"
						ZIndex="1" />
					<Grid
						x:Name="FolderItemTemplateGrid"
						ColumnDefinitions="Auto, *, Auto"
						ColumnSpacing="5"
						Margin="10,2"
						ZIndex="1000">
						<Label
							Grid.Column="0"
							FontFamily="SegoeUiRegular"
							FontSize="14"
							Text="{Binding Email.SenderEmail.ShortDisplayName}" />
						<Label
							Grid.Column="1"
							FontFamily="SegoeUiRegular"
							FontSize="14"
							Margin="10,0,0,0"
							MaximumWidthRequest="1000"
							Text="{Binding Email.Subject}" />
						<Label
							Grid.Column="2"
							FontFamily="SegoeUiRegular"
							FontSize="14"
							Margin="10,0,0,0"
							Text="{Binding Email.MessageDate}" />
					</Grid>
				</Grid>
			</ViewCell>
		</DataTemplate>
	</ListView.ItemTemplate>
</ListView>

There are two things to note here:

  1. The tap gesture works so it knew enough to dereference the relative sourcing to the gesture handler
  2. You can see that I declare the datatype at the DataTemplate level: x:DataType="viewModels:EmailViewModel" I know this works because intellisense was able to find all of the properties after I typed Email 'dot' field name (even the Email 'dot' SenderEmail 'dot'

Does any of that make sense?

mobycorp avatar Jun 30 '22 13:06 mobycorp

Thanks for the kind words, appreciate it! 😄

The XAML I used is in that sample repo I posted. I didn't link it up the right way here, but you should be able to see my full reproduction here: https://github.com/jfversluis/Repro8433 for the bits and pieces you posted that is what it boiled down to according to me.

The thing that stands out in your opening post, is that the error states it's looking for the Email property on the EmailsViewModel notice the plural in this case. This is also reflected in your screenshot you posted in your last message. So it seems like something is mixed up in the scopes of things.

While reviewing your code I think I see what's up... Maybe. I see you set the x:DataType on the DataTemplate I vaguely recall doing that one time and it not working. Could you move that down to the ViewCell or the Grid maybe? Does that change it?

jfversluis avatar Jun 30 '22 13:06 jfversluis

Hi @mobycorp. We have added the "s/needs-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.

ghost avatar Jun 30 '22 13:06 ghost

@jfversluis You picked up on the exact issue that I am trying to describe.

  1. The data context for the page is the EmailsViewModel (again, you noticed correctly it is the plural view model - the master if you will)
  2. I explicitly set the data context for the item template by stating x:DataType="viewModels:EmailViewModel" (not plural - the detail view model)
  3. I looked at your repo and the way you defined both view models looks correct.

Unless I don't understand fully what the x:DataType declaration does, I would think that would allow the parser to correctly map the properties in the detail view model (EmailViewModel)

mobycorp avatar Jun 30 '22 13:06 mobycorp

@jfversluis Some additional detail... This is the code-behind of the content page:

namespace MobyClient.Pages;
public partial class PageEmails : ContentPage {
	public PageEmails (EmailsViewModel emailsViewModel) {
		Guard.IsNotNull (emailsViewModel);
		InitializeComponent ();
		BindingContext = emailsViewModel;
	}
}

mobycorp avatar Jun 30 '22 13:06 mobycorp

@mobycorp

  • do you get that error at runtime or compile time
  • running in DEBUG or RELEASE. does it happens on both ?
  • how are you setting your list view item source
  • are you sure EmailViewModel has a public Email property ?

We tried to come up with a repro, based on the scarce info you gave us, but that repro is working well. I'm sorry about your severe deadlines, and the impact on your work-life balance. We understand the sense of urgency, and this is why you got quick answers. If you really need this investigated, you definitely have to provide the smallest possible project that triggers this behaviour, and we will look at it. Thanks

Here are the answers to your questions:

  1. Runtime
  2. Debug
  3. I supplied code for the code-behind of the content page in a reply to Gerald below which is for EmailsViewModel (notice the plural of Emails - this is the master viewmodel) as the binding context
  4. Yes, EmailViewModel (the detail viewmodel) has a public property Email

mobycorp avatar Jun 30 '22 13:06 mobycorp

x:DataType is a compiled binding, it does not set the BindingContext, it should work even removing it.

What that does is to resolve the binding expressions at compile-time rather than runtime speeding up the binding process and also allows the intellisense in the xaml editor to suggest the properties for you reporting build errors when invalid properties are found.

Ok, that is exactly what I supposed x:DataType did. So, when in the xaml editor and I type Email.Subject and no squiggly lines are there AND it was able to find the properties and properties of properties, I would expect it to NOT report binding errors. That is the basic crux of what I am reporting.

mobycorp avatar Jun 30 '22 14:06 mobycorp

If you remove the DataType in the ItemTemplate it will force the DataType you probably defined in your ContentPage expecting to find "Email" in EmailsViewModel, with "classic bindings" you should remove that too

Anyway the error shouldn't allow you to compile so that seems a bit different from what is happening to you...

As Gerald said, probably there's something about setting the DataType to the DataTemplate that gives you those errors at runtime

PentaTech avatar Jun 30 '22 14:06 PentaTech

I am experiencing the same issue and have created a repro here: https://github.com/willshoemaker/MauiRepro8433

If the collection property on the view model is set prior to setting the view model as the binding context I do not experience a binding error, but if I set the value of the collection property later (in this case via a delayed Loaded event handler) there are binding errors for each property on each item in the collection. Note that despite the binding errors it appears to be displaying correctly, though it does not respond to XAML hot reload. I have only tested the issue on the Windows platform.

These errors occur both when the content of the ViewCell is in the initial page and also when it is in a separate ContentView

willshoemaker avatar Jul 06 '22 20:07 willshoemaker

I'm seeing the same issue as described by willshoemaker. If I switch from ListView to CollectionView the problem goes away.

andrewhenry3 avatar Sep 07 '22 13:09 andrewhenry3

Like andrewhenry3, I experienced the same issue as willshoemaker, and (same as andrewhenry3), when I switched from ListView to CollectionView the problem went away.

anthony-glenwright avatar Sep 28 '22 00:09 anthony-glenwright

CollectionView worked for me too and since it has all the functionality of the ListView and more you could just use the CollectionView. More info on the difference between the 2 can be found in this video

mStylias avatar Oct 29 '22 08:10 mStylias

This looks eerily similar to a long outstanding bug in Xamarin.Forms. If the code was copy-pasted over to Maui, then solving the problem here might also warrant a backported fix for Xamarin.Forms?

DDHSchmidt avatar Nov 17 '22 15:11 DDHSchmidt

Related to https://github.com/dotnet/maui/issues/11956

Maybe a duplicate?

mattleibow avatar Dec 08 '22 11:12 mattleibow

I get the same errors,

[14:03:18 WRN] 'TestString' property not found on 'MyApp.ViewModels.TestViewModel', target property: 'UraniumUI.Material.Controls.TextField.Text'

and I have A LOT of properties on the page. I can reproduce that the error is generated depending on whether it is a read-only property.

I.e., the warning will be generated if the property has only a getter and no setter.

<Entry Text="{Binding TestString}" />
public string TestString => "Test"; // (erroneous) warning
public string TestString { get; set; } = "Test" // no warning

StepKie avatar Mar 05 '23 13:03 StepKie

I think I'm seeing the same issue, here's my repro project: https://github.com/spadapet/maui_bugs

Build and run the "BadBindingFailure" project in that solution.

Click between the Test X tabs and it creates unnecessary binding failures which you can see in the VS binding failures window. The wrong data context is temporarily used:

image

image

spadapet avatar Mar 17 '23 16:03 spadapet

Same here, had to switch to a CollectionView to stop the false binding errors. Just want to be sure that I'm using the most optimized approach to displaying simple list items.

DamianSuess avatar Apr 11 '23 08:04 DamianSuess

I'm also having the same issue and switching to a CollectionView fixed it.

squeezeoj avatar May 14 '23 13:05 squeezeoj

I also have this problem. I read that eveybody fixes it by using the CollectionView, but I'm already using it, so that's weird. I tried to make a reproducable sample, but in this sample it did not occur. This makes me unsure about the cause.

For me the errors are in the output window when when I run the debug version of my (windows) app.

sjorsmiltenburg avatar Jun 09 '23 13:06 sjorsmiltenburg

I'm facing the same warning but the ListView displays the items as expected. I have my XAML:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
	     xmlns:converter="clr-namespace:LanguageInUse.ValueConverters"
	     xmlns:lang="clr-namespace:LanguageInUse"
	     xmlns:dt="clr-namespace:LanguageInUseApp.Domain;assembly=LanguageInUseApp.Domain"
             x:Class="LanguageInUse.Views.DictionaryList"
             x:Name="dictionaryList"
             Title="{lang:Translate Title}">
	<ListView x:Name="listDictionaries" ItemsSource="{Binding Dictionaries}">
		<ListView.ItemTemplate>
			<DataTemplate>
				<ViewCell>
					<Grid>
						<Grid.RowDefinitions>
							<RowDefinition Height="*" />
							<RowDefinition Height="*" />
						</Grid.RowDefinitions>
						<Grid.ColumnDefinitions>
							<ColumnDefinition Width="100" />
							<ColumnDefinition Width="*" />
						</Grid.ColumnDefinitions>

						<Label Text="{Binding Name}"
							FontSize="18"
							FontAttributes="Bold"
							Grid.Column="1" />
						<Label Text="{Binding Description}"
							FontSize="12"
							Grid.Column="1" Grid.Row="1" />
					</Grid>
				</ViewCell>
			</DataTemplate>
		</ListView.ItemTemplate>
	</ListView>
</ContentPage>

In my ContentPage class I have the constructor

DictionaryListViewModel vm;

public DictionaryList(DictionaryListViewModel model)
{
    vm = model;
	BindingContext = vm;
        
	InitializeComponent();
}

I tried to add in DataTemplate, ViewCell and in the Grid the property `x:DataType="dt:Dictionary" that is the basic data model I use. The ViewModel has

[ObservableProperty] private List<Dictionary> _dictionaries;

that is translate in Dictionaries in the XAML via CommunityToolkit.Mvvm.

Do you have any idea how to fix it?

erossini avatar Jul 19 '23 16:07 erossini

I'm facing the same warning but the ListView displays the items as expected. I have my XAML: ... Do you have any idea how to fix it?

Switching your ListView to a CollectionView will solve this problem. At the end of the day it turns out to be a beneficial move, and CollectionView can be more performant 👍

DamianSuess avatar Jul 20 '23 19:07 DamianSuess

Still happening to me even with CollectionView using the latest Maui packages for .NET 8 preview (8.0.0-preview.7.8842).

I've attached a minimal repro. Initial page load looks fine, but as soon as I hit the "Load more" button to modify the collection I see binding errors in the debugger. Seems the binding first fails by trying to bind to the view model and only then falls back to using the correct binding context (which in this case is the People property in the view model).

These binding failures spam my logs, and I am trying to understand if these also cause bad performance.

image

MauiApp1.zip

remoba avatar Aug 14 '23 19:08 remoba

Similarly to the versions just above me; but for me CollectionView shows the same endless stream of wrong bindings and doesn't end up loading anything and crashes out (though that might be something else's fault). ListView shows the endless stream of wrong bindings but ends up falling back to the right thing and things are displayed properly, albeit seemingly with a performance issue.

ransagy avatar Aug 14 '23 21:08 ransagy

Verified this issue with Visual Studio Enterprise 17.8.0 Preview 1.0. Can repro on windows platform. maui_bugs-main.zip MauiRepro8433-master.zip image

Zhanglirong-Winnie avatar Sep 07 '23 08:09 Zhanglirong-Winnie

I have the same problem here. My bindings work as expected, but the xaml compiler throws me error messages. However, I can launch and use the application as expected. The problem occurs in the ListView for me.

DOsterholz avatar Sep 14 '23 07:09 DOsterholz