The following forum(s) are migrating to a new home on Microsoft Q&A (Preview): Developing Universal Windows apps!

Ask new questions on Microsoft Q&A (Preview).
Interact with existing posts until December 13, 2019, after which content will be closed to all new and existing posts.

Learn More

 none
Sorting Listview resets the SelectedItem property RRS feed

  • Question

  • Hi,

    basically I stumbled across this issue:

    https://bengribaudo.com/blog/2010/09/14/199/keeping-selected-item-selected-when-changing-listviews-itemssource/comment-page-1?unapproved=88417&moderation-hash=4f244e91363349e3b625ff44be716cb2#comment-88417

    I've got a ListView that I want to sort. I want to keep the selecteditem selected after the sorting operation. The problem I have is that the selecteditem is reset for a very small time to null, that I want to avoid, because other bindings rely on this property. This issue is described in the last part of the post, but not solved.

    I tried to add an additional _isSorting boolean, without luck:

    private void SortConversations()
    {
        _isSorting = true;
        _conversations.Sort(model => model.LastMessageTimeStamp, descending: true);
        _isSorting = false;
    }
    
    public ConversationViewModel SelectedConversation
    {
        get => _selectedConversation;
        set
        {
            if (!_isSorting)
            {
                Set(ref _selectedConversation, value);
            }
        }
    }

    The problem is, that the Item does not appear as selected in the UI. Even if I try to manually set it again, it requires some additional Task.Delay() between the sort and the (re)selection. That is no proper solution, especially if the pc running the app is slower or faster.

    Do you have a better idea?

    Monday, November 25, 2019 1:26 PM

All replies

  • Hi,

    When the order of the data set changes, if the UI change is triggered, the HashCode of the generated UI item will also change.

    This is the internal design.

    You can listen to the ListView's ItemClicked event or the SelectionChanged event, and create a backup of the ListView.SelectedItem in time so that it can be selected according to the backup settings during the next reorder.

    In addition, you may try to use the ObservableCollection, which has special optimizations for UWP to enhance its reusability.

    By the way, We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!

    Best regards.


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.


    Monday, November 25, 2019 2:40 PM
  • Thanks for your help Richasy,

    I've already tried all the solutions you described. I am using an observable collection and Move() the items. I've also tried to backup the SelectedItem, but as I said it is null for a small time amount. And If I reselect the item, I need to add a delay between the Sorting and the reselection. And that is exactly the problem I am facing. How can I solve this?

    I've prepared a minimal example, so you can test the problem real quick:

    https://github.com/AtosNicoS/ListViewSortIssue

    To reproduce the issue:

    1. Click "Reset" Button

    2. Select any item

    3. Click "Sort" Button

    4. Watch and Repeat

    What you will see is, that sometimes (50% of the time) after the sorting a wrong(!!) item gets selected. With the additional delay, the correct item will be selected after one second. That is one issue I am focussing.

    The other issue is, that SelectedItem is reset to null while sorting the list. I've added code to work around this issue with the _isSorting boolean. It is currently not activated, but should work commented out. You said, observable collections should work better here - they do not. The value is still null. And the issue even becomes more complicated, combined with the delay issue described above.

    In my real application (with more data and larger datatemplates) this issue becomes even more complicated. If the selected item is at the top of the list, the sorting+selection works without delay, if it is in the bottom of the list, the item is not selected after sorting anymore.

    Adding a delay does not sound like the right solution. I somehow need to wait until the ListView refreshed its items.

    Any ideas?

    Tuesday, November 26, 2019 9:20 AM
  • Hi,

    I found the solution, in fact this is a problem with the UI refresh mechanism.

    Modify your SortButton_OnClick method

    private void SortButton_OnClick(object sender, RoutedEventArgs e)
    {
        var tmp = SelectedItem;
    
        TestListView.ItemsSource = null;
        ListViewItemViewModels.Sort(x => x.Count);
        TestListView.ItemsSource = ListViewItemViewModels;
    
        SelectedItem = tmp;
    }

    When you use ObservableCollection, UWP optimization mainly lies in the reuse of UI components, and this reuse sometimes comes with state.

    When we actively disconnect the ObservableCollection from the UI when sorting, then the UI will be forced to refresh and the state of all UI components will be reset, so we can set the selected item.

    By the way, We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!

    Best regards.


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.


    Tuesday, November 26, 2019 2:56 PM
  • Hi,

    that is basically a workaround, but no real solution. Setting the whole list to null might solve the sort issue, but generates other issues in my code, because other code refers to that list, which is now null!

    I made another interesting observation:

    If I replace the following line in my example:

    //ListViewItemViewModels.Sort(x => x.Count);
    ListViewItemViewModels.Move(0,1);
    and click on any element in the middle of the list and then "sort" (move element[0] to element[1]), the (re)selection is completely wrong. Only after some delay the selection is correct again. That sounds like a bug to me. There seems to be obviosly wrong with the ListView regarding move operations that should be investigated, isnt it?

    Wednesday, November 27, 2019 8:01 AM
  • Hi,

    As I said, the list items generated with the ObservableCollection will have UI reuse. This is the way ListView saves system resources.

    I re-tested your code and found a place that could cause conflict:

    <DataTemplate x:DataType="local:ListViewItemViewModel">
    	<ListViewItem IsSelected="{x:Bind IsSelected, Mode=TwoWay}">
    		<TextBlock Text="{x:Bind Count, Mode=OneTime}"></TextBlock>
    	</ListViewItem>
    </DataTemplate>
    

    Here you bind the ListViewItemViewModel.IsSelected property of ListViewItem.IsSelected.

    After I tried to replace ListViewItem with Grid and removed the IsSelected property binding, everything worked fine and we didn't need to set ListView.ItemsSource to null.

    Here I can give you some suggestions:

    1. If the IsSelected property is only a property for create the UI effects, it is recommended to delete.

    First, you can get the selected item directly by getting ListView.SelectedItem.

    Second, you can get the selected item through the ListView.ItemClick or ListView.SelectionChanged event and save it as a variable.

    2. If the IsSelected property will affect other data structures.

    You can also adjust the property in ListView.ItemClick or ListView.SelectionChanged, but do not let it directly bind to UI related properties.

    Best regards.


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.

    Wednesday, November 27, 2019 2:40 PM
  • Hi,

    Does my reply solve your problem? Do you have any other questions you want to clarify?

    The UWP section of MSDN is about to be locked down. If you have other questions, please come to Microsoft Q&A to ask questions, and we will continue to answer your questions there.

    Best regards.


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.

    Tuesday, December 3, 2019 8:10 AM
  • Hi,

    Sorry to disturb you again, we are confirming the status of the question. Did my response resolve your issue?

    Since the UWP section of the MSDN Forum will be locked down in the near future, after that, if you have new questions, welcome to our new community: Microsoft Q&A, where we will continue to answer your questions.

    Best regards.


    "Developing Universal Windows apps" forum will be migrating to a new home on Microsoft Q&A (Preview)!
    We invite you to post new questions in the "Developing Universal Windows apps" forum’s new home on Microsoft Q&A (Preview)!
    For more information, please refer to the sticky post.

    Friday, December 6, 2019 6:24 AM