#ListView questions

1 messages · Page 1 of 1 (latest)

random trellis
#

Okay, I've pretty much figured out how it works, so I now have a function

private void Test()
{
   Debug.Log("Hello")
}```
which I add to my ItemsAdded event with
```c
MyListView.ItemsAdded += objects => Test();

which allowed me to discover that the event occurs before my new item is added to my list, so I have the following question: "Is there a way to access the object that will be created in my Test function?"

random trellis
#

I just discovered that although Items.Added is called before the creation of the corresponding object in my listview it is called after the change of size of my list in the instance of my class but modifying the new element of my list (in my case modifying the value of my enum at the last position of my list) does not modify the visual object created.

finite ice
#

You mean you're doing objects[0].value = newvalue in ItemsAdded?

random trellis
#

hmmm no I'm doing this

int index = property.FindPropertyRelative("Condition").arraySize - 1;
property.FindPropertyRelative("Condition").GetArrayElementAtIndex(index).enumValueIndex = 2;

since doing

int index = property.FindPropertyRelative("Condition").arraySize - 1;
Debug.Log(MyListView[index]);

Give me a null value as if the new element in my ListView hadn't yet been created

finite ice
#

Can you show the whole method you're calling ItemsAdded

random trellis
#

the first exemple is my whole code so far and here is the version with my declaration

Conditions.itemsAdded += objects => 
{
    int index = property.FindPropertyRelative("Condition").arraySize - 1;
    property.FindPropertyRelative("Condition").GetArrayElementAtIndex(index).enumValueIndex = 2;
};
#

I also tried to create myseld the new element with

MyListView.contentContainer.Add(new EnumField());

Who give me a NullReferenceException when I try to add a new element

tame walrus
#

the name "Condition" caught my attention, so can I ask what tool you are writing? 😄

random trellis
tame walrus
#

yeah seems doable ig by passing a source list and desired value to some custom property attribute, isnt it?

#

or more like source list's serialized property name proapbly

finite ice
#

So, your property in your propertydrawer is the list right?

#

Or you have a custom editor that then has a ListView and property is the collection?

#

Can you log property.FindPropertyRelative("Condition").arraySize in that method and see if it is the value you expect

#

I'm guessing that'll be the old size of your collection
I.e. your collection size is 10, you press add, itemsAdded gets called and logs 10, size then increases to 11

#

Meaning you're not actually editing the right property

random trellis
random trellis
finite ice
#

What type is the parameter you get from itemsAdded?

#

(unity docs doesn't say)

random trellis
#

System.Collections.Generic.IEnumerable<int>

finite ice
#

How are you constructing your listview?

tame walrus
#

w8... so you want to show an object field only if list INSIDE that object contains a specific value?

random trellis
finite ice
#

You should be iterating over the objects list and modifying those indexes only instead of the last one fwiw (probably not the issue though)

#

Can you show the uxml it generates for the list view specifically

random trellis
#
 <ui:ListView focusable="true" reorderable="true" show-border="true" show-foldout-header="true" show-add-remove-footer="true" binding-path="Conditions" show-bound-collection-size="true" header-title="Conditions" selection-type="Single" virtualization-method="DynamicHeight" name="Conditions" style="max-height: 4000px;" />
tame walrus
#

for some reason I cant read xml XD

finite ice
#

Ok, given that I don't have the source in front of me

#

I'd guess that a serializedObject.ApplyModifiedProperties() call at the end of itemsAdded will fix the issue

tame walrus
#
[System.AttributeUsage(System.AttributeTargets.Field)]
public class ShowIfAttribute : PropertyAttribute
{
    public string listPropertyName;
    public string requiredValue;

    public ShowIfAttribute(string listPropertyName, string requiredValue)
    {
        this.listPropertyName = listPropertyName;
        this.requiredValue = requiredValue;
    }
}
#
[CustomPropertyDrawer(typeof(ShowIfAttribute))]
public class ShowIfDrawer : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        ShowIfAttribute showIfAttribute = attribute as ShowIfAttribute;
        SerializedProperty listProperty = property.serializedObject.FindProperty(showIfAttribute.listPropertyName);

        if (listProperty != null && listProperty.isArray)
        {
            bool showProperty = false;
            for (int i = 0; i < listProperty.arraySize; i++)
            {
                SerializedProperty elementProperty = listProperty.GetArrayElementAtIndex(i);

                if (elementProperty.stringValue == showIfAttribute.requiredValue)
                {
                    showProperty = true;
                    break;
                }
            }
            if (showProperty)
            {
                return base.CreatePropertyGUI(property);
            }
        }
        return new VisualElement();
    }
}

I jsut dusyred out this thing

#

this is using a string but can be altared easyly to enum ig

random trellis
finite ice
# random trellis Beautiful that's work 😮

Cool, so I think what's happening is that Unity is creating an instance and adding it to the backing list (without serializedProperties involved) and then calling SerializedObject.Update to update the SO instance

#

That then overrides the SO and your changes are discarded

random trellis
random trellis