Quick answer: BindItem must reset every visual aspect from the data model. Don’t store row state on the element — pooling reuses elements across indices. Track selection in data; render in BindItem.
Scroll a ListView; rows show wrong colors or selection state. The recycled element kept state from the previous index.
The Symptom
Scrolling reveals incorrect highlight, color, or sub-element values. State only matches data after a re-bind / refresh.
The Fix
listView.makeItem = () => new VisualElement();
listView.bindItem = (el, i) =>
{
var data = items[i];
el.Q<Label>("name").text = data.Name;
el.EnableInClassList("selected", listView.selectedIndices.Contains(i));
el.EnableInClassList("alert", data.HasAlert);
el.RemoveFromClassList("hover"); // reset transient
};
listView.unbindItem = (el, i) =>
{
// optional: clean up event subscriptions
};
Every visual aspect set explicitly. Class list reset. No leakage between rows.
Selection in Data
Use ListView’s selectedIndex and selectedIndices APIs. Don’t store “am I selected” on the element. BindItem queries the canonical selection state.
Verifying
Scroll the ListView. Rows should show correct state at each position. Without the fix: visible flicker between recycle events.
“Reset every aspect in BindItem. Selection in data. Pool reuses safely.”
Related Issues
For UI Toolkit USS @import, see USS @import. For dynamic styles, see dynamic styles.
Bind from data. Reset transient. Pool clean.