Search code examples
c#linqlambdakendo-ui-mvckendo-ui-grid

How can I provide default expression in the { } of a lambda expression, while still allowing it to be added to?


I am using the Kendo UI MVC Grid and I want to encapsulate boilerplate code so I don't have to duplicate the same code on every grid. Configuring the commands on the grid looks like this:

columns.Command(command =>
            {
                command.Custom("Edit").Text("<span class='k-icon k-edit'></span>").Click("editRecord");
                command.Custom("Delete").Text("<span class='k-icon k-i-delete'></span>").Click("deleteItem");
            }).Width(130);

The edit and delete are boilerplate, however there is a potential for extra custom commands depending on the grid. The type of the lambda for command is of Action<GridActionCommandFactory<T>>. How can I abstract the boilerplate to a method or something while still allowing custom commands to be entered? Psuedo-coding it out I figure it would look something like this:

columns.Command(command =>
            {
                //Custom commands here
                SomeConfigClass.DefaultGridCommands(command);
                //Custom commands here
            }).Width(130);

or maybe:

columns.Command(command =>
            {
                //Custom commands here
                command.DefaultCommands();
                //Custom commands here
            }).Width(130);

And this would include the edit and delete commands. But I have no idea how to modify a lambda expression in such a way, how can I achieve this?


Solution

  • Well I did some more digging and it ended up not being that hard. Not sure if it's the most elegant solution but I did it like this:

    public static Action<GridActionCommandFactory<T>> GetDefaultGridCommands<T>(Action<GridActionCommandFactory<T>> customCommandsBeforeDefault = null, Action<GridActionCommandFactory<T>> customCommandsAfterDefault = null) where T : class
        {
            Action<GridActionCommandFactory<T>> defaultCommands = x =>
            {
                x.Custom("Edit").Text("<span class='k-icon k-edit'></span>").Click("editRecord");
                x.Custom("Delete").Text("<span class='k-icon k-i-delete'></span>").Click("deleteItem");
            };
    
            List<Action<GridActionCommandFactory<T>>> actions = new List<Action<GridActionCommandFactory<T>>>();
    
            if(customCommandsBeforeDefault != null)
                actions.Add(customCommandsBeforeDefault);
            actions.Add(defaultCommands);
            if(customCommandsAfterDefault != null)
                actions.Add(customCommandsAfterDefault);
    
            Action<GridActionCommandFactory<T>> combinedAction = (Action<GridActionCommandFactory<T>>) Delegate.Combine(actions.ToArray());
    
            return combinedAction;
        }
    

    Then calling it in the grid:

    columns.Command(KendoUiGridConfig.GetDefaultGridCommands<MyViewModel>()).Width(130);
    

    The Delegate.Combine method was what I was looking for.