For my custom editor window I have a ListView that shows a list of scriptable objects from my assets folder. Is it possible to rename them from the list view as we would a gameobject in the hierarchy and how would I go about implementing that?
When creating the element that the ListView is showing you can register for KeyDownEvent and MouseDownEvent callbacks. For the KeyDownEvent you can check if the KeyCode is F2 and then start the name change. For the MouseDownEvent there is no way to assure the click is a slow double click so you would have to do that manually by setting a timer when the item is first selected (using the ListView.selectionChanged property). Then in the MouseDownEvent callback check that a certain amount of time has passed and that the clicked item is the selected item (ListView.selectedItem or ListView.selectedIndex).
To perform the actual name change, I would add TextField to the selected element with isDelayed set to true. Then register for a ChangeEvent callback to set the name of your corresponding ScriptableObject, then remove the TextField. You would likely have to register for some other events like FocusOut to make sure the TextField is removed when no new text is entered.
Hope all that made sense!
Ahh I see. I ended up changing my approach. In my custom window I have a button that creates a new scriptable object and adds it to the list of the listview, I thought, I should be able to rename the scriptable object after it’s created, but now I’m using EditorUtility.SaveFilePanelInProject() and it’s a much nicer workflow to name new scriptable objects. So now my follow up question is, how can I refresh the ListView after I added the new item to the list? I tried ListView.Refresh() but it gives me an error that an object is destroyed and I’m trying to access it. The error points to my bindItem action. Any help is appreciated.
Would help to see some of your code, like the bindItem and makeItem implementations.
Fair enough. I run this method when the editor window opens
private void ListViewInitialization()
{
VisualElement makeItem() => new Label();
Action<VisualElement, int> bindItem = (e, i) => (e as Label).text = editingSegment.data.obstacleLayouts[i].name;
layoutsListView = editorContainer.Q<ListView>(name = "layouts-listview");
layoutsListView.itemsSource = editingSegment.data.obstacleLayouts;
layoutsListView.makeItem = makeItem;
layoutsListView.bindItem = bindItem;
layoutsListView.selectionType = SelectionType.Single;
layoutsListView.onItemChosen += OnLayoutSelected;
}
“obstacleLayouts” is the list I’m displaying. And here’s where I create a new item on the list (newLayout) and try to refresh the list.
private void CreateLayout()
{
string savePath = EditorUtility.SaveFilePanelInProject("Save Layout", "NewLayout", "asset", "");
ObstacleLayout newLayout = new ObstacleLayout();
AssetDatabase.CreateAsset(newLayout, savePath);
editingSegment.data.obstacleLayouts.Add(newLayout);
layoutsListView.Refresh();
}
Edit: I think it might be that “newLayout” is the instance and not the .asset file so it get’s destroyed. I’ll try loading the asset from with the savePath and see if things work properly
Edit #2: That seemed to be problem, it’s working correctly now!