UWP: BindingExpression errors in ListView with a heterogeneous collection

Recently, I got BindingExpression exceptions when was creating some UI with ListView:

Error: BindingExpression path error: ‘Weight’ property not found on ‘HeterogeneousListView.Data.Milk, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Weight’ DataItem=’HeterogeneousListView.Data.Milk, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

Error: BindingExpression path error: ‘Liters’ property not found on ‘HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Liters’ DataItem=’HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

Error: BindingExpression path error: ‘Weight’ property not found on ‘HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Weight’ DataItem=’HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

You might seen similar errors when trying to bind a data item to a wrong template. The difference in my case is that the UI looked well, without any visible issues. I prepared a test project to reproduce the bug. The code is at github.

The test application shows some heterogeneous data in a ListView. My test data is three objects: Cookie, Milk and Orange.

There are two lists in the app. The lists have various approaches of applying a DataTemplate for an ItemContainer. For the left ListView, I set the ListView.ItemContainerSelector property to an instance of my custom DataTemlateSelector:

As you noticed, I override DataTemplateSelector.SelectTemplateCore
to choose a template for a data item. If you scroll down the left list, you immediately will see the errors in Debug Output window of VisualStudio. The fact, that the errors are appearing when scrolling the list, made me think that the realization of items works wrong. And most probably the bug in ProductTemplateSelector. If uncomment the debug lines in ProductTemplateSelector.SelectTemplateCore method, the output will show something interesting:


Container for: Orange 3

Data Cookie 98

Error: BindingExpression path error: ‘Pieces’ property not found on ‘HeterogeneousListView.Data.Orange, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Pieces’ DataItem=’HeterogeneousListView.Data.Orange, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)


Container for: Orange 4

Data Orange 99


Container for: Cookie 98

Data Cookie 98


Container for: Orange 99

Data Orange 99

It says that an ItemContainer is being reused for a data item and DataTemplate.SelectTemplateCore is being executed twice for the same data item.

In fact, DataTemplateSelector has two versions of SelectTemplateCore:

And which version a developer needs to utilize depends on underlying ItemsPanel. If you use GridView or ListView with ItemsStackPanel or with ItemsWrapGrid then SelectTemplateCore(Object) needs to be overriden. By default, the underlaying panel for ListView and GridView is ItemsStackPanel. But if ItemsPanel is VirtualizingStackPanel or WrapGrid then SelectTemplateCore(Object, DependencyObject) should be implemented. The rule applies to any ItemsControl.

I override the wrong version of SelectTemplateCore in my ProductTemplateSelector. That’s the origin of the error. Uncomment ProductTemplateSelector.SelectTemplateCore(Object) in the example, run the app. The list now works smoothly.

What I also want to show you is how to apply a DataTemplate for an ItemContainer without using ListView.ItemContainerSelector. Starting from Windows 10, ListView and GridView controls have a new  ListViewBase.ChoosingItemContainer event.

In the test app, the ListView with custom implementation of ChoosingItemContainer is shown at the right part of the MainPage. And the handler for the event is very simple:

 

Needless to say, that ChoosingItemContainer gives better control when creating an item container. DataTemplateSelector is very simple to use and it does what it does. But when it requires to gain some performance benefits, then the best way is to implement a handler for ChoosingItemContainer event. You can also get more ideas about the usage of the new event from MSDN.

Fruitful coding!


Leave a Reply