I have a custom Editor for a scriptableObject. This scriptableObject has List i wanted to display and manipulate within a ListView. I tried to model this after the tank example.
When the list gets big enough that the scrollbar gets visible and i scroll an entrie which is moved out of sight gets inserted at another place in my list.
At this point my list has only empty entries except the last shown with test:
after scrolling up it this entrie is somehow also in a random top entrie:
and the bottom one is still present.
Here my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UIElements;
[CustomEditor(typeof(TemplatePathsSO))]
public class TemplatePathsSOEditor : Editor
{
private TemplatePathsSO templatePathsSO;
private VisualElement root;
private VisualTreeAsset visualTree;
private ListView templateList;
public void OnEnable(){
templatePathsSO = (TemplatePathsSO)target;
root = new VisualElement();
visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/UI/TemplatePathsSOUI.uxml");
}
public override VisualElement CreateInspectorGUI()
{
root.Clear();
Button plusButton = new Button();
plusButton.name = "plusButton";
plusButton.text = "+";
if (plusButton != null)
{
plusButton.clickable.clicked += () =>
{
templatePathsSO.templatePaths.Insert(0, new TemplatePath());
templateList.Refresh();
};
}
root.Add(plusButton);
visualTree.CloneTree(root);
templateList = root.Q<ListView>("templateList");
if (templateList != null)
{
templateList.selectionType = SelectionType.None;
if (templateList.makeItem == null)
templateList.makeItem = MakeItem;
if (templateList.bindItem == null)
templateList.bindItem = BindItem;
templateList.itemsSource = templatePathsSO.templatePaths;
templateList.Refresh();
}
return root;
}
private VisualElement MakeItem()
{
var element = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/UI/TemplatePathUI.uxml").CloneTree();
element.style.flexDirection = FlexDirection.Row;
element.style.height = 20;
Button plusButton = new Button();
plusButton.name = "plusButton";
plusButton.text = "+";
element.Add(plusButton);
Button minusButton = new Button();
minusButton.name = "minusButton";
minusButton.text = "-";
element.Add(minusButton);
return element;
}
private void BindItem(VisualElement element, int index)
{
TemplatePath templatePath = templatePathsSO.templatePaths[index];
TextField templateName;
templateName = element.Q<TextField>("templateName");
templateName.value = templatePath.templateName;
templateName.RegisterValueChangedCallback( ctx => {
templatePath.templateName = (string) ctx.newValue;
});
TextField pathString;
pathString = element.Q<TextField>("pathString");
pathString.value = templatePath.pathString;
pathString.RegisterValueChangedCallback( ctx => {
templatePath.pathString = (string) ctx.newValue;
});
var selectButton = element.Q<Button>("selectPath");
if (selectButton != null)
{
selectButton.clickable.clicked += () =>
{
string path = EditorUtility.OpenFilePanel("Choose Template", "Assets", "txt");
if (path.Length > 0)
{
templatePath.pathString = path;
pathString.value = templatePath.pathString;
}
};
}
var plusButton = element.Q<Button>("plusButton");
if (plusButton != null)
{
plusButton.clickable.clicked += () =>
{
templatePathsSO.templatePaths.Insert(index + 1, new TemplatePath());
templateList.Refresh();
};
}
var minusButton = element.Q<Button>("minusButton");
if (minusButton != null)
{
minusButton.clickable.clicked += () =>
{
templatePathsSO.templatePaths.RemoveAt(index);
templateList.Refresh();
};
}
}
}