Listview.Clear() does not appear to work for me.

Hello,

It seems to me that listview.Clear() doesn’t work in my case, although it seems to be used without problems by most people. I must be doing something wrong, but I don’t understand what. (Or I don’t understand clearly what listView.Clear() does).

Here is my code to test the command (tested in 2020.3 mostly, but the problem of clear not clearing appeared for me at first in 2020.2), my listView contains some items:

        ListView listView;
        private void OnEnable()
        {
            listView = rootVisualElement.Query<ListView>(name: "ListMenu").First();

            Button button = new Button();
            button.text = "Clear";
            VisualElement butt = button;
            butt.styleSheets.Add(styleSheet);
            butt.name = "ClearButton";
            root.Add(butt);
            button.clickable.clicked += () => listView.Clear();
        }

When I press my button, nothing happens, my listView keeps the different elements it has.

I looked at the code of unity 2020.2 (GitHub - Unity-Technologies/UnityCsReference at 61f92bd79ae862c4465d35270f9d1d57befd1761), there is a clear definition inside Modules/UIElementsEditor/controls/ListViewBindings.cs, and it has a throw new NotImplementedException(); in it, but i don’t think it is related, as nothing appears when I press the button.

However, the documentation tells me the clear function comes from VisualElement.Clear(), so I looked at the definition of this particular clear:

        /// <summary>
        /// Remove all child elements from this element's contentContainer
        /// </summary>
        public void Clear()
        {
            if (contentContainer == this)
            {
                hierarchy.Clear();
            }
            else
            {
                contentContainer?.Clear();
            }
        }

Which should work as the documentation says, that is, find the content container that holds my Listview items, and clear those items.
The problem first appeared when I tried to bind a different list of inferior size of the precedent list, into my listvew, after of course a Listview.clear();
I’m not a very skilled programmer, so I’m not at all sure that I understand well how UIElements works, so any clue on how to make it work is welcome!

ListView uses makeItem/bindItem delegates to manage the list of children. You should never call .Add/Remove or Clear() directly.

In your case, you can just reassign the itemSource of your ListView to the new list and makeItem/bindItem will be called to fill with the new content.

When you change the content of the list, you can call Refresh() to get the ListView populated with your new elements.

        List<string> items;
        private void OnEnable()
        {
             //Q is an alias for Query(..).First() that doesn't perform gc allocations
            listView = rootVisualElement.Q<ListView>(name: "ListMenu");
            items = new List<string>(){"first,"second", "third"};
        
            listView.makeItem = () => new Label();
            listView.bindItem = (e, i) => ((Label)(e)).text = items[i];
 
            listView.itemsSource = items;

            Button button = new Button();
            button.text = "Clear";
            VisualElement butt = button;
            butt.styleSheets.Add(styleSheet);
            butt.name = "ClearButton";
            root.Add(butt);
            button.clickable.clicked += () => {items.Clear();listView.Refresh();}
        }

Superb! It’s much clearer now why I couldn’t get it to work. My scripts are working fine now. Thanks a lot!

1 Like