Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to add items to a ListView at runtime

Discussion in 'UI Toolkit' started by AnduraStudio, Jun 24, 2022.

  1. AnduraStudio

    AnduraStudio

    Joined:
    Jul 31, 2019
    Posts:
    2
    Hi!

    I modified Unity's sample ListView code to add new elements to a ListView in runtime on UI Toolkit.

    When the user clicks on the button, the code adds a new element to
    items 
    List

    The List<string> is updated but the ListView is not. Until I resize my "Game" viewport. Then the items appear on the ListView.

    My question: How do I force the UI to update?

    Unity version: 2021.2.7f1

    Here's some prints:
    After clicking the "New Item" button a bunch of times:


    After resizing my "Game" viewport:



    UIDemoController.cs
    Code (CSharp):
    1. using System;
    2.     using System.Collections;
    3.     using System.Collections.Generic;
    4.     using Unity.VisualScripting;
    5.     using UnityEditor;
    6.     using UnityEngine;
    7.     using UnityEngine.Serialization;
    8.     using UnityEngine.UIElements;
    9.     using Random = UnityEngine.Random;
    10.  
    11.     public class UIDemoController : MonoBehaviour
    12.     {
    13.         public VisualTreeAsset ListItem;
    14.         private VisualElement root;
    15.         private List<string> items;
    16.         private ListView listView;
    17.  
    18.  
    19.         private void Start()
    20.         {
    21.             // ListItem = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/UI/Demo/item.uxml");
    22.             root = GetComponent<UIDocument>().rootVisualElement;
    23.             var btn = root.Q<Button>("add-new-item");
    24.             btn.clicked += AddNewItem;
    25.  
    26.             // Create some list of data, here simply numbers in interval [1, 1000]
    27.             // const int itemCount = 5;
    28.             items = new List<string>();
    29.             // for (int i = 1; i <= itemCount; i++)
    30.             //     items.Add(i.ToString());
    31.  
    32.     // The "makeItem" function will be called as needed
    33.     // when the ListView needs more items to render
    34.             Func<VisualElement> makeItem = () => ListItem.CloneTree();
    35.  
    36.     // As the user scrolls through the list, the ListView object
    37.     // will recycle elements created by the "makeItem"
    38.     // and invoke the "bindItem" callback to associate
    39.     // the element with the matching data item (specified as an index in the list)
    40.             Action<VisualElement, int> bindItem = (e, i) =>
    41.             {
    42.                 e.Q<Label>("CharacterName").text = items[i];
    43.                 e.Q<VisualElement>("bg").style.backgroundColor = new StyleColor(GetRandomColor());
    44.             };
    45.  
    46.             listView = root.Q<ListView>();
    47.             listView.makeItem = makeItem;
    48.             listView.bindItem = bindItem;
    49.             listView.itemsSource = items;
    50.             listView.selectionType = SelectionType.Multiple;
    51.  
    52.     // Callback invoked when the user double clicks an item
    53.             listView.onItemsChosen += Debug.Log;
    54.  
    55.     // Callback invoked when the user changes the selection inside the ListView
    56.             listView.onSelectionChange += Debug.Log;
    57.  
    58.         }
    59.  
    60.         private void AddNewItem()
    61.         {
    62.             Debug.Log("Clicked");
    63.             items.Add((items.Count + 1).ToString());
    64.             // listView.itemsSource = items;
    65.             // listView.visible = !listView.visible;
    66.         }
    67.  
    68.         private Color GetRandomColor()
    69.         {
    70.             var r = Random.Range(0f, 1f);
    71.             var g = Random.Range(0f, 1f);
    72.             var b = Random.Range(0f, 1f);
    73.  
    74.             return new Color(r, g, b, 1f);
    75.         }
    76.     }
     

    Attached Files:

    Last edited: Jun 24, 2022
  2. AnduraStudio

    AnduraStudio

    Joined:
    Jul 31, 2019
    Posts:
    2
    I added
    listView.Refresh();
    inside AddNewItem() and it seems to work.

    Is that the proper way to update my ListView on runtime?
     
    niuage and rinat24mai2000 like this.
  3. niuage

    niuage

    Joined:
    Nov 17, 2019
    Posts:
    88
    I think the method is now called `Rebuild`, it's the idea!
     
  4. griendeau_unity

    griendeau_unity

    Unity Technologies

    Joined:
    Aug 25, 2020
    Posts:
    230
    Yes, if you add items to your `itemsSource`, you need to call `RefreshItems` after you're done, so that the list updates correctly. `Rebuild` is a bit more intense as it will recreate all elements instead of reusing them. This one should be called if your item template changes for example.
     
    Mj-Kkaya and f4bo like this.
  5. niuage

    niuage

    Joined:
    Nov 17, 2019
    Posts:
    88
    Ah yes, thanks for the info, RefreshItems works great, I'll switch to that.
     
    griendeau_unity likes this.
  6. Mj-Kkaya

    Mj-Kkaya

    Joined:
    Oct 10, 2017
    Posts:
    156
    Thanks for the topic, it's really helps me.