Here’s a functional EditorWindow
using a data-bound ListView
with customized items (simple labels) and buttons to create / delete / clear the list.
<ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" xsi="http://www.w3.org/2001/XMLSchema-instance" engine="UnityEngine.UIElements" editor="UnityEditor.UIElements" noNamespaceSchemaLocation="../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:ListView focusable="True" selection-type="Multiple" reorderable="true" item-height="16" name="items" show-bound-collection-size="false" style="flex-grow: 1;" />
<ui:VisualElement style="flex-direction: row; justify-content: flex-end;">
<ui:Button text="+" name="items-add" tooltip="Add new item." />
<ui:Button text="-" name="items-delete" tooltip="Delete selected items." />
<ui:Button text="Clear" name="items-clear" tooltip="Clear all items." />
</ui:VisualElement>
</ui:UXML>
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
[EditorWindowTitle(title = "Item Library")]
public class ItemLibrary : EditorWindow
{
// using the window itself as an example container
[SerializeField] private List<string> m_Items = new List<string>();
private ListView m_ListView;
private SerializedProperty m_ListProperty;
[MenuItem("Testing/Item Library")]
public static void ShowExample()
{
GetWindow<ItemLibrary>().Show();
}
public void OnEnable()
{
var root = rootVisualElement;
// instantiate the window UI
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/ItemLibrary/ItemLibrary.uxml");
visualTree.CloneTree(root);
var listView = root.Q<ListView>("items");
var dataContext = new SerializedObject(this);
var listProperty = dataContext.FindProperty(nameof(m_Items));
// bind this ListView to the m_Items list
listView.BindProperty(listProperty);
// important, otherwise the item at index 0 is expected to bind to the Array.size property
listView.showBoundCollectionSize = false;
// customize the list items look and feel
// note: if you don't set these callbacks, PropertyField will be used to bind each list item
listView.makeItem = MakeItem;
listView.bindItem = BindItem;
m_ListView = listView;
m_ListProperty = listProperty;
var addButton = root.Q<Button>("items-add");
addButton.clicked += AddItem;
var deleteButton = root.Q<Button>("items-delete");
deleteButton.clicked += DeleteSelectedItems;
var clearButton = root.Q<Button>("items-clear");
clearButton.clicked += ClearItems;
}
private void ClearItems()
{
Undo.RecordObject(this, "Clear items");
m_Items.Clear();
}
private void DeleteSelectedItems()
{
if (!m_ListView.selectedIndices.Any())
return;
Undo.RecordObject(this, "Remove selected items");
foreach (var selectedIndex in m_ListView.selectedIndices.OrderByDescending(i => i))
{
m_Items.RemoveAt(selectedIndex);
}
}
private void AddItem()
{
Undo.RecordObject(this, "Add new item");
m_Items.Add("Item " + m_Items.Count);
}
private VisualElement MakeItem()
{
// TODO: instantiate some UXML template here
return new Label();
}
private void BindItem(VisualElement target, int index)
{
var bindable = (BindableElement)target;
bindable.BindProperty(m_ListProperty.GetArrayElementAtIndex(index));
}
}