How to pass a local object to a ContextualMenuManipulator / ContextualMenuPopulateEvent

I know I can do this with an anonymous lambda, but they make me cringe a bit…

Semi-Pseudo code:

string importantDataString = "want to pass along this string";
foldout.AddManipulator(new ContextualMenuManipulator(CreateFoldoutContextMenu));

void CreateFoldoutContextMenu(ContextualMenuPopulateEvent evt)
{
    evt.menu.AppendAction("Do Something Important", DoSomethingImportant);
}

void DoSomethingImportant(DropdownMenuAction obj)
{
    Debug.Log("Want to do something special with the [importantDataString ] here. but can't");
}

Looks like there’s an overload that takes user data: Unity - Scripting API: UIElements.DropdownMenu.AppendAction(string,Action<DropdownMenuAction>,Func<DropdownMenuAction,DropdownMenuAction.Status>,object)

And this gets passed to DropdownMenuAction.userData.

1 Like

That would fix steps 2 and 3, but leave me stuck with the lambda for step 1 no?

This multi-level lambda works, but feels meh…

foldout.AddManipulator(new ContextualMenuManipulator(@event =>
{
    var hasFilesToDownload = data.filesByDataset.TryGetValue(dataset, out var iFiles);
    @event.menu.AppendAction("Download All Files in Dataset", _ =>
        {
            Debug.LogWarning(hasFilesToDownload
                ? $"Download [{iFiles.Count}] files in dataset: [{dataset.Name}]"
                : "No Files to Download"); 
        },
        hasFilesToDownload
            ? DropdownMenuAction.Status.Normal
            : DropdownMenuAction.Status.Disabled);
}));

I don’t think you’re going to around this without making some kind of object to contain the string, which is effectively what the syntax sugar of a lamda function is doing for you.

And honestly lambas’s are fine for editor code. I avoid them in runtime or in performance critical points, but don’t care about the allocations of one-off firing delegates.

Use the language features to your advantage :u

1 Like