I’m using UIToolkit to draw a serialized dictionary. I can see the listview element using the UI Toolkit debugfer, but I can’t query it in the code. How can I get a reference to the listview?
using System.Linq;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
namespace Attributes.Editor
{
[CustomPropertyDrawer(typeof(SerializedDictionary<,>))]
public class SerializedDictionaryDrawer : PropertyDrawer
{
private PropertyField elem;
public override VisualElement CreatePropertyGUI(SerializedProperty property)
{
elem = new PropertyField(property);
elem.name = "test";
elem.RegisterCallback<AttachToPanelEvent>(OnAttachToPanel);
void OnAttachToPanel(AttachToPanelEvent evt)
{
var listview = elem.Q<ListView>();
Debug.Log($"listview:{listview == null}");
}
return elem;
}
private void OnItemIndexChanged(int id1, int id2)
{
Debug.Log($"id1:{id1},id2:{id2}");
}
}
}
I want to make a serialized dictionary, get the listview, listen to the element index change event, and then update the _indexByKey dictionary
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
[Serializable]
public class SerializedDictionary<TK,TV> : IDictionary<TK,TV>,ISerializationCallbackReceiver
{
[Serializable]
private struct KeyValuePair
{
[SerializeField] private TK _key;
[SerializeField] private TV _value;
public KeyValuePair(TK key, TV value)
{
_key = key;
_value = value;
}
public TK key{ get => _key; set => _key = value;}
public TV value { get => _value; set => _value = value;}
}
[SerializeField]
private List<KeyValuePair> _pairs = new();
private readonly Dictionary<TK, int> _indexByKey = new();
private readonly Dictionary<TK, TV> _dictionary = new();
[SerializeField, HideInInspector] private bool error;
public SerializedDictionary(){}
public SerializedDictionary(IDictionary<TK, TV> source)
{
foreach (var pair in source)
{
Add(pair.Key,pair.Value);
}
}
public int Count => _dictionary.Count;
public bool IsReadOnly => false;
public ICollection<TK> Keys => _dictionary.Keys;
public ICollection<TV> Values => _dictionary.Values;
public TV this[TK key]
{
get => _dictionary[key];
set
{
_dictionary[key] = value;
if (_indexByKey.ContainsKey(key))
{
var index = _indexByKey[key];
_pairs[index] = new KeyValuePair(key, value);
}
else
{
_pairs.Add(new KeyValuePair(key, value));
_indexByKey.Add(key,_pairs.Count - 1);
}
}
}
public void Add(TK key, TV value)
{
_pairs.Add(new KeyValuePair(key,value));
_dictionary.Add(key,value);
_indexByKey.Add(key,_pairs.Count - 1);
}
public bool ContainsKey(TK key)
{
return _dictionary.ContainsKey(key);
}
public bool Remove(TK key)
{
if (_dictionary.Remove(key))
{
var index = _indexByKey[key];
// var removed = _pairs[index];
var last = _pairs[^1];
var lastKey = last.key;
var lastIndex = _pairs.Count - 1;
if (_pairs.Count > 1)
{
_pairs[index] = last;
// _pairs[lastIndex] = removed;
// _indexByKey[key] = lastIndex;
_indexByKey[lastKey] = index;
}
_pairs.RemoveAt(lastIndex);
_indexByKey.Remove(key);
return true;
}
return false;
}
public bool TryGetValue(TK key, out TV value)
{
return _dictionary.TryGetValue(key, out value);
}
public void Clear()
{
_pairs.Clear();
_dictionary.Clear();
_indexByKey.Clear();
}
public Dictionary<TK, TV> BuildNativeDictionary()
{
return new Dictionary<TK, TV>(_dictionary);
}
public void Add(KeyValuePair<TK, TV> pair)
{
Add(pair.Key,pair.Value);
}
public bool Contains(KeyValuePair<TK, TV> pair)
{
if (_dictionary.TryGetValue(pair.Key,out var value))
{
return EqualityComparer<TV>.Default.Equals(value, pair.Value);
}
return false;
}
public void CopyTo(KeyValuePair<TK, TV>[] array, int arrayIndex)
{
ICollection collection = _dictionary;
collection.CopyTo(array,arrayIndex);
}
public bool Remove(KeyValuePair<TK, TV> pair)
{
if (_dictionary.TryGetValue(pair.Key,out var value))
{
var isEqual = EqualityComparer<TV>.Default.Equals(value, pair.Value);
if (isEqual)
{
return Remove(pair.Key);
}
}
return false;
}
public IEnumerator<KeyValuePair<TK, TV>> GetEnumerator()
{
return _dictionary.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _dictionary.GetEnumerator();
}
public static implicit operator Dictionary<TK, TV>(SerializedDictionary<TK, TV> serializedDictionary)
{
return serializedDictionary._dictionary;
}
public static implicit operator SerializedDictionary<TK, TV>(Dictionary<TK, TV> dictionary)
{
return new SerializedDictionary<TK, TV>(dictionary);
}
public void OnBeforeSerialize()
{
}
public void OnAfterDeserialize()
{
_dictionary.Clear();
_indexByKey.Clear();
error = false;
for (int i = 0; i < _pairs.Count; i++)
{
var key = _pairs[i].key;
if (key != null && !ContainsKey(key))
{
_dictionary.Add(key,_pairs[i].value);
_indexByKey.Add(key,i);
}
else
{
error = true;
}
}
}
}