Dynamics 365

Dynamics 365 Command Bar Customisation: A Practical Guide

Custom buttons look easy until they vanish for every user except you. Here is how I build them properly.

Dynamics 365 Command Bar Customisation: A Practical Guide

Dynamics 365 command bar customisation is one of those jobs that looks simple until you try it, and then you lose a whole afternoon to a button that refuses to appear. I have customised more command bars than I care to count, and the pattern is always the same. Somebody asks for "just one extra button", and three days later the whole thing is held together with JavaScript and hope.

The good news is that the modern approach is far better than the old ribbon XML days. Here is how I do it now, and the traps I wish I had known about earlier.

What the command bar actually is

The command bar is the row of buttons across the top of a form, a view or a subgrid in a model driven app. It replaced the old ribbon, and it is now configured through a proper designer in Power Apps rather than hand edited XML.

Every button is a command. Each command has an action (what it does), a visibility rule (when it shows) and sometimes an enable rule (when it can be clicked). Get those three straight in your head and most of the confusion goes away.

Command designer versus Ribbon Workbench

For years the Ribbon Workbench was the only sensible option, and I still respect it for older projects. For anything new I use the built in command designer, because it is supported, it lives inside the solution and nobody has to install a third party tool on the client environment.

The designer is not perfect. Complex visibility logic is still clumsy, and some of the older system buttons cannot be touched. But for 90 percent of requests it does the job in minutes.

Adding a custom button the sensible way

Start with the question nobody asks: does this really need to be a button? If the user needs to do something to a record, a button is right. If you are just trying to show a bit of information, put it on the form instead. Good form design beats a cluttered command bar every time.

When a button is justified, the steps are straightforward.

The basic steps

Open the app in the designer, pick the table and choose where the command goes: main form, main grid, subgrid or associated view. Add a new command, give it a clear label and icon, and point it at a JavaScript function or a Power Fx formula.

Put your JavaScript in a web resource and keep it small. One function per command, one job per function. If you find yourself writing two hundred lines in a command handler, the logic belongs in a plugin or a flow and the button should just call it.

Power Fx commands: the quick win

This is the bit that has genuinely changed my working life. Power Fx commands let you write a formula directly in the designer, with no web resource at all. Patching a field, navigating to another record or showing a notification can be done in a line or two.

For simple actions it is brilliant. A "Mark as reviewed" button that sets a choice field and saves the record takes about two minutes. Compare that with the old route of writing JavaScript, publishing a web resource, registering the ribbon rule and then clearing your browser cache for the fifth time.

The limit is complexity. The moment you need conditional calls to external services or lots of branching, move back to JavaScript or call a Power Automate flow. Do not force a formula to do a developer's job.

Visibility rules without the headaches

Most of the pain is visibility. A button shows for you as a system administrator, then vanishes for everyone else, and you cannot work out why.

Nine times out of ten the answer is security. The user does not have the privilege on the table, or the button depends on a field they cannot read. Check the security roles before you touch a single line of code. I once spent an hour debugging a button that was working perfectly, because the tester's role simply had no write access.

Use formulas for visibility, not hard coded roles

Base visibility on data, not on who someone is. Show the button when the status is Draft, or when a particular field has a value. Tying buttons to named users or teams creates a maintenance headache the moment someone changes job.

Common mistakes I keep seeing

The first is too many buttons. A command bar with fifteen custom actions is a user adoption problem waiting to happen, and I have written about that in my post on getting users to actually use the system. Be ruthless. If a button is used twice a month, hide it in the overflow or remove it.

The second is forgetting solutions. Do your command changes in an unmanaged solution, and add them to your pipeline properly. Making edits straight in production is how you end up with a different command bar in test and live. My guide to application lifecycle management covers how to avoid that.

The third is leaving old customisations behind. Existing ribbon XML from earlier projects often collides with new commands, and the result is duplicate buttons or ones that quietly stop working. Audit what is already there before you add anything.

A quick checklist before you ship

Test with a user who has the lowest security role, not your admin account. Test on the form, the grid and the subgrid, because the same command can behave differently in each. Test on mobile if your users are out and about, since some commands do not render there.

Finally, name things properly. "Button1" in a solution is a gift to whoever inherits your work, and that person might well be you in a year.

If your command bar has turned into a mess, or you are planning a rollout and want it done properly first time, have a look at my Dynamics 365 consulting services. And if you like practical, no nonsense advice on building things quickly, my book The 28 Day Startup is for you.

More from the blog

Dynamics 365•6 min read

Dynamics 365 Form Design: How to Build Forms People Actually Use

Read more
Business•7 min read

Five Things I Learned Bootstrapping Five Businesses

Read more
Technology•6 min read

Why I Still Build in .NET After 17 Years (And Have No Plans to Change)

Read more