TreeView - How to override input?

I have a TreeView, and I’d like right & left input to do something other than expand / collapse tree view items. That is, a left or right input would not collapse or expand an item, but invoke whatever I have bound to those events (increment / decrement an item value in this case). I thought this might be simple, but a brief look around TreeView/BaseTreeView/etc. classes makes it seem like input / navigation is pretty locked down for these classes? Is what I’m trying to do practically achievable?

Hello!

I have a small question - just for my own clarity! When incrementing/decrementing said value, are you focusing on an element inside the TreeView, e.g: a Button/TextField/etc? Or are you trying to override the TreeView item’s expand/collapse when pressing right/left key which means the items in your TreeView are not expandable at all?

Hi, thanks for your time.

Items in my tree view are expandable / collapsible, and are represented by a pair of Labels.
The ideal here is to only expand / collapse items via a “submit”-like input, and cycle values with left/right inputs.
I’m currently handling the former (expanding/collapsing) via a method subscribed to TreeView.itemsChosen.

This image should help demonstrate what I’m talking about -

Thank you for sharing your use case, I see your intent now.

I don’t see any easy way to achieve this but to override the TreeView’s behaviour a bit. It’s not ideal but you can do something like the following:

treeView.scrollView.contentContainer.AddManipulator(new KeyboardNavigationManipulator((operation, event) =>
{
    switch (operation)
    {
        case KeyboardNavigationOperation.MoveRight:
            event.StopImmediatePropagation();
            // ...
            break;
        case KeyboardNavigationOperation.MoveLeft:
            event.StopImmediatePropagation();
            // ...
            break;
    }
}));

The above should allow you to stop the default behaviour, by calling StopImmediatePropagation, if said condition matches your case. Otherwise, allow the standard flow to happen.

The above was close. Breakpoints were hit when I expected them to be, but propagation did not seem to actually be stopped (L/R still collapses/expands tree view items).
I’m not sure but I suspect there is another KeyboardNavigationManipulator somewhere that is utilizing this event before my code does.

Side note - I was going to try removing a KeyboardNavigationManipulator a line before adding my own, but the example shown at Unity - Manual: Manipulators (myElement.RemoveManipulator<ExampleDragger>();) doesn’t reflect how manipulators are actually removed. You need an IManipulator reference and there doesn’t seem to be any accessible ones in the tree view class hierarchy.

Anyway, similar code that ended up working -

m_treeView.Q<ScrollView>().contentContainer.RegisterCallback<NavigationMoveEvent>(_event =>
{
    switch(_event.direction)
    {
        case NavigationMoveEvent.Direction.Up: break;
        case NavigationMoveEvent.Direction.Down:  break;
        case NavigationMoveEvent.Direction.Left: _event.StopImmediatePropagation(); break;
        case NavigationMoveEvent.Direction.Right: _event.StopImmediatePropagation(); break;
    }
}, TrickleDown.TrickleDown);
2 Likes