locked
No selectionchanged event when ListView becomes empty

    Question

  • Hi,

    I have a list view where I can select items and delete them. Apparently, deleting an item changes the selection, because the previously selected items are gone after deleting them, yielding an empty selection. Most of the times, these selection changes cause the 'selectionchanged' event of the ListView to be fired.

    However, when I select and delete the last item from the ListView, the 'selectionchanged' is not fired.

    The ListView uses a custom IListDataSource (using an IListDataAdapter and VirtualizedDataSource) that calls NotificationHandler.reload() instead of NotificationHandler.invalidateAll() to notify the ListView (see http://social.msdn.microsoft.com/Forums/en-US/winappswithhtml5/thread/84a170d6-e13a-46ac-b8aa-6db41f3bd775). So maybe the different behavior is caused by the different notifications being called? I too a short look at the WinJS sources and it looks like the 'selectionchanged' is only fired when there is an "updater". But since reload() is not an updating operation, there is no "updater".

    Is this a bug or am I using the API wrong?

    Thanks,

    Guido

    Monday, March 19, 2012 2:35 PM

All replies

  • I'm not answering the question directly but it looks ok to me even it doesn't fire selectionchanged event as actually there is nothing selected after all items are deleted. Can you work around it by additional code?
    Tuesday, March 20, 2012 9:48 AM
  • I think it should fire the 'selectionchanged' event, because before deleting the item, it was selected, and after deleting it, nothing is selected, so clearly the selection did change. So far, I haven't found a feasible workaround.


    • Edited by gdoo Tuesday, March 20, 2012 10:48 AM
    Tuesday, March 20, 2012 10:48 AM
  • Hi Guido,

    I found a bug against this for an earlier version.  Did you create a new project in the Consumer Preview or are you on an earlier build.  Can you post a simple repro here?

    -Jeff


    Jeff Sanders (MSFT)

    Wednesday, March 21, 2012 7:49 PM
    Moderator
  • Hi Jeff,

    I have created a simple project demonstrating that a ListView's 'selectionchanged' event is not fired when a data source sends the reload() notification:

    http://dl.dropbox.com/u/60029335/NoSelectionChangedOnReload.zip

    Thursday, March 22, 2012 10:21 AM
  • Hi Guido,

    The ListView does not fire the selectionChanged event the datasource does.  Your customer dataSource is not firing a selectionChanged event so that is why you are not getting one.

    Take a look at how the listView samples work.  For example, load this sample:

    http://code.msdn.microsoft.com/windowsapps/ListView-custom-data-4dcfb128

    Put a breakpoint in the ui.js file at the line 22828 _fireSelectionChanging.

    Then run scenario 3 and remove the selected item.  You can use the provided data classes to get this functionality or you can modify your custom data classed to mimic this behaviour.  Same for your previous thread about reload etc...

    Always remember... The debugger is your friend!  Use it to see how the samples work and you will be able to do all sorts of cool custom stuff on your own!

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, March 22, 2012 8:04 PM
    Moderator
  • Hi Jeff,

    I'm sorry but I'm not following.

    First of all, thank you for the advice, I have already spent a reasonable amount of time in the debugger trying to understand the inner workings of WinJS. The fact that ui.js is 32000 (!) lines long does not make it a particularly joyful experience. Call stacks that only start at the most recent event handler also make it hard to get the "big picture".

    Second, the _fireSelectionChanging function you mentioned is part of the WinJS.UI._SelectionManager which is used as this._selection in WinJS.UI.ListView. So, at what point of the story are selections and the corresponding events handled/fired by the data source instead of the ListView, as you say? Why should a data source know about the concept of selection anyway? The documentation mentions a selectionchanged event for ListView, while the only event for IListDataSource is statuschanged. Actually, I do get selectionchanged events (from my ListView) most of the times, without my custom data source implementation firing them explicitly -- they are generated (in ListView._synchronize()) when I call invalidateAll() on the IListDataNotificationHandler that is passed to my IListDataAdapter implementation (in IListDataAdapter.setNotificationHandler()). I just don't get the events when I call reload() on it.

    Third, as far as I can tell, the example shows how selectionchanged events are fired when I modify an IListDataSource directly using its own methods, e.g. remove(). It does not cover the case where the data represented by a data source is modified from somewhere else and the data source is only notified about these changes by the IListDataNotificationHandler passed to the IListDataAdapter inside the data source.

    Cheers,

    Guido

    Friday, March 23, 2012 9:14 AM
  • Hi Guido,

    Sorry I sent you into the debugger, I assumed you would learn much more from that experience!

    Yes the selection manager does fire the event.  This is also fired from _synchronize on the ListView which can be called from _update.

    _synchronize and _set are the only two places where _fireSelectionChanged are fired.

    endEdits is called on the itemData source in the sample which in turn ultimate fires _synchronize.

    This in turn calls DataSource endEdits (through the bindings), ultimately calling update.

    You can of course trace through all of this and do the same think in your data class.  Out of curiosity, why are you not using the provided classes so you can avoid all of this hassle?

    -Jeff


    Jeff Sanders (MSFT)

    Friday, March 23, 2012 1:21 PM
    Moderator
  • Hi Jeff,

    I'm not sure which "provided classes" you are referring to. WinJS.Binding.List? Our data lives inside an SQLite DB, and there can be lots of data, so we don't want to load everything into the memory-based Binding.List. We do use a "provided class", WinJS.UI.VirtualizedDataSource, which is intended to be used with a custom implementation of the IListDataAdaper interface -- like the bingImageSearchDataAdapter in the example you mentioned.

    I still think that it is a perfectly valid use case to have a list view with a virtualized data source that uses a data adapter that at some point calls reload() on the notification handler. I also think that it is correct to expect a 'selectionchanged' event from the list view if an item was selected and the reload() causes it to disappear from the list view. The selection used to contain that item, now it doesn't contain any item, so apparently it changed! But the event is not fired. This is a bug, isn't it? (In case this explanation is too vague, please look at the code I posted earlier.)

    If it is not a bug, how exactly should I change my code to get that 'selectionchanged' event?

    Guido

    Friday, March 23, 2012 2:37 PM
  • Guido,

    This is not a bug.

    The sample I reference shows how to create customzied data sources using WinJS.Binding.List.  Using that as a basis for your code you will see that it will correctly call synchronize and in turn call the selectionChanged event.  Ultimately you could call the event yourself however if you cannot use the provided samples and modify it for your use.

    Debugging your code is a bit beyond the scope of help that I can provide in a Forum post.  If we start from a published sample I can certainly assist you there.  That said, you can certainly follow the patterns that the BindingList does and implement that in your code.  Again, this excersise it left up to you however.  I have attempted to explain to you how the sample works and how these events get fired.  I appologise if we are not connecting here, but I am unsure how else to explain this to you.

    Drill into the sample code as it shows you 3 different ways to work with data sources and adapt your code to build on this sample.  Again, the debugger will help you if you step through the successful vs. failed case.

    Make sense?

    -Jeff


    Jeff Sanders (MSFT)

    Friday, March 23, 2012 2:58 PM
    Moderator
  • Also Guido,

    I am not aware of any problems if you follow this: http://msdn.microsoft.com/en-us/library/windows/apps/Hh770849.aspx or the samples to create a custom data source.  Perhaps if you backtrack and follow these examples we can work together to help you get on the right track?

    -Jeff


    Jeff Sanders (MSFT)

    Friday, March 23, 2012 3:36 PM
    Moderator
  • Hi Jeff,

    I get the feeling that we're at cross-purposes.

    My custom data source is implemented following the documentation. My issue occurs in an advanced scenario that is not covered by the documentation or the sample, namely using the notification handler, specifically its reload() method.

    I tried explaining the issue 3 times and I wrote code that reproduces it. That's all I can do, my boss wants me to get back to work now.

    Thanks for your efforts.

    Guido

    Monday, March 26, 2012 7:55 AM
  • Sorry Guido,

    The fastest way to connect would be if you can provide me a project that reproduces the problem.  Apparently we are having difficulty communicating via the forum.

    -Jeff


    Jeff Sanders (MSFT)

    Thursday, April 12, 2012 5:06 PM
    Moderator
  • Hi Jeff,

    Thanks for following up.

    This project reproduces the problem. It might seem contrived, but that's only because most of the DataAdapter logic from the original project was stripped.

    Guido

    Friday, April 13, 2012 7:51 AM
  • I will take a look.  Thanks!

    Jeff Sanders (MSFT)

    Tuesday, April 17, 2012 3:46 PM
    Moderator