Strange bug in ListView: appending new items readds existing items

Daljit Singh 261 Reputation points
2020-01-30T13:43:11.887+00:00

So I have a very strange bug using ListView. I have an which is essentially a ListView of a custom control object, which is simply a Grid wrapped around an InkCanvas. I have a Button that adds new items to an ObservableCollection which is the ItemSource for the ListView. Adding items works well, but the problem is that after adding several items the ListView doesn't append "blank" InkCanvas objects, instead sometimes it appends InkCanvas controls that are already present in the list. So for example if I draw something on the first 5 canvases, adding a new canvas (sometimes) re-adds a new canvas which contains the strokes from the previous canvases.

Here is a full video that shows the bug Imgur Video showing the bug

And I have also created a Sample Git Repo that reproduces the bug here https://github.com/daljit97/ListViewAddingTest

Universal Windows Platform (UWP)
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Fay Wang - MSFT 5,196 Reputation points
    2020-01-31T02:21:11.437+00:00

    Hello,​

    ​Welcome to our Microsoft Q&A platform!

    This issue is caused by UI virtualization in ListView. It means that UI elements representing the items are created on demand. For an items control bound to a large collection, it would be a waste of resources to create the UI for all the items at the same time, because they can't all be displayed at the same time. ListView perform UI virtualization for you. When items are close to being scrolled into view, the framework generates the UI for the items and caches them. When it's unlikely that the items will be shown again, the framework re-claims the memory. When continuing to scroll, it will reuse the cached items. About more details, you can refer to: ListView and GridView UI optimization.

    The ListView's default ItemsPanelTemplate has an ItemsStackPanel which uses virtualization, so in that case, you can define your own ItemsPanel. For example:

    < ListView>  
            ......  
            < ListView.ItemsPanel>  
                < ItemsPanelTemplate>  
                    < StackPanel Orientation="Vertical"/>  
                < /ItemsPanelTemplate>  
            < /ListView.ItemsPanel>  
            ......  
        < /ListView>  
    

  2. 小雄 1 Reputation point
    2020-10-07T10:16:17.167+00:00

    您的問題就是缺乏 Binding 及 inkCanvas 的畫面儲存,ListView 的每個 item 都要有 id property,再將 id Binding 到 ListView。

    例如在您的範例 ListViewAddingTest 中 CanvasControl 必須增加一個 id property,並將 inkCanvas 的畫面記錄到獨立的 buffer 或 file,每次當 CanvasControl id 被更改時就要根據 id 從 Buffer 或 file 中讀出 inkCanvas 的畫面,並重繪其內容。

    以上必須採用 Binding 方式才能做到,如此就能保留 ItemsStackPanel 的虛擬化功能,並正確的顯示每個 CanvasControl 所繪製的內容,真正的虛擬化就是要這樣做才對。

    0 comments No comments