Bug 55928 - Cell's Command.CanExecute being called with incorrect objects in ListView on UWP
Summary: Cell's Command.CanExecute being called with incorrect objects in ListView on UWP
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms ()
Version: 2.3.5
Hardware: PC Windows
: High major
Target Milestone: ---
Assignee: Chris King
Depends on:
Reported: 2017-05-03 18:37 UTC by Adam Patridge [MSFT]
Modified: 2017-06-14 21:00 UTC (History)
5 users (show)

Tags: ac
Is this bug a regression?: ---
Last known good build:

Sample project reproducing issue on UWP (337.84 KB, application/x-zip-compressed)
2017-05-03 18:37 UTC, Adam Patridge [MSFT]

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Adam Patridge [MSFT] 2017-05-03 18:37:45 UTC
Created attachment 21925 [details]
Sample project reproducing issue on UWP

UWP appears to be calling each ListView Cell's Command.CanExecute method with parameters that don't make sense. 

Attached is a repro solution where a cell MenuItem is bound to call a custom ICommand implementation. Inside the custom implementation is the following CanExecute method:

> public bool CanExecute(object parameter)
> {
>   log.Add("CanExecute: " + ((parameter == null) ? "(null)" : parameter.GetType().Name));
>   return false;
> }

When run, the resulting output is a repeat of these lines for each cell in the list:
> CanExecute: (null)
> CanExecute: People
> CanExecute: Person
> {repeated 4 additional times}

# Steps to reproduce
1. Create new blank Xamarin.Forms solution
2. Create a custom Command class with some code in CanExecute that expects to work with an object from a cell of the list we will create next
3. Create a model for your page with a Command for a cell MenuItem to execute
4. Add a ListView to the MainPage.xaml with a TextCell that has a MenuItem bound to call the Command above with the cell's object as the CommandParameter
5. Run the app with some data

# Expected behavior
It should only call CanExecute with the cell's data

# Actual behavior
It appears to call multiple times: once with null, once with the ListView full bound object, and once with the cell's bound object.

This issue doesn't happen on iOS or Android.

# Test environment (full version information)
> Microsoft Visual Studio Enterprise 2017
> Version 15.1 (26403.7) Release
> VisualStudio.15.Release/15.1.0+26403.7
> Microsoft .NET Framework
> Version 4.6.01586
> ...
> Visual Studio Tools for Universal Windows Apps   15.0.26403.07
> The Visual Studio Tools for Universal Windows apps allow you to build a single universal app experience that can reach every device running Windows 10: phone, tablet, PC, and more. It includes the Microsoft Windows 10 Software Development Kit.
>Xamarin (3f99c5a)
>Visual Studio extension to enable development for Xamarin.iOS and Xamarin.Android.
>Xamarin.Android SDK (b16fb82)
>Xamarin.Android Reference Assemblies and MSBuild support.
>Xamarin.iOS and Xamarin.Mac SDK (7656cc6)
>Xamarin.iOS and Xamarin.Mac Reference Assemblies and MSBuild support.
Comment 1 Chris King 2017-06-14 20:32:22 UTC
We expect to be able to call CanExecute whenever we want for whatever reason. In this case we call it more frequently on UWP than the other platforms. This may not be optimal but CanExecute must not expect the optimal case. Instead, the invariant is that on all platforms the last call to CanExecute before accepting user input will be with the same parameter.

Just for reference: In this case, the context is changed from nothing, to the inherited view, to the one specified by the app in the following three locations:



Comment 2 Chris King 2017-06-14 20:45:45 UTC
All that said, we're gonna look at optimizing the code.