Colored tabs in Visual Studio

Do you have many tabs in Visual Studio with designers and code editors and do you struggle to make sense of them? It’s not surprising – we often work with many things at once and some elements even have same names (e.g. VendTable table and form), which means that tabs for them look identical.

Original view of tabs (no colors)

Wouldn’t it be great if, for example, tabs for tables had a different color than tabs for forms?

It can be done…

Open Visual Studio and go to Tools > Extensions and Updates. Switch to Online and find and install Productivity Power Tools.

Note that Power Tools contain many more features than just tab coloring. You probably want to review them and configure them as needed (which might also mean disabling some of them).

Open Tools > Options and switch to Productivity Power Tools > Custom Document Well. Uncheck Color tabs by project and tick Color tabs by regular expression.

Then go to Productivity Power Tools > Custom Document Well > Advanced and tick Use full document path for regular expression matching.

Then it’s time to define colors and rules for using them. The setup we’ve just done allows us to find patterns in paths of files used in tabs. For example, if I open VendTable table in the designer, the path (in my environment) is K:\AosService\PackagesLocalDirectory\ApplicationSuite\Foundation\AxTable\VendTable.xml. If I want to assign a color to all tabs with table designers, I can use a regular expression like .*\\AxTable\\.*. It finds paths containing \AxTable\.

This setup is done under Productivity Power Tools > Custom Document Well > Color Coding.

Here is an example of how we can use it.

Configuration of tab colors

Here I’ve decided to use different colors for designers and code editors. For example, a tab with table editor has a dark red color, while opening code for the table creates a tab with a lighter red color. The same is done for classes, just using green color instead of red.

This is what I can see in Visual Studio:

Colored tabs

Now I can clearly distinguish element types and if I remember my setup, I can even immediately say which tab is for which type.

By the way, I could also go to Custom Document Well options and set Place tabs on the Left to display tabs vertically:

Vertical tabs

If you prefer, you can set colors based on something else than element types. For example, you could use different colors for elements from different packages. You’re limited only by what information you can extract from file paths.

It works nicely in both Visual Studio 2015 and Visual Studio 2017. Unfortunately it’s not supported in Visual Studio 2019, although there seem to be ways how to get it working.

FormObservableLink works in data source extensions

FormObservableLink class is useful for refreshing display and edit methods in D365FO. You create an instance variable of FormObservableLink type in a form, initialize it and call its observe() method in display/edit methods that you need to refresh on demand. When the refresh is required, you call markChanged() method of FormObservableLink and the system will rerun the methods and display new values. You can find more details in AX 7. Display methods and Form Observability, for instance.

I wondered if I can do the same in a data source extension and I wasn’t really should that it would work. But it does – and the implementation is virtually the same as when building a whole form.

Here is a simple example:

[ExtensionOf(formDataSourceStr(smmContactPerson, ContactPerson))]
final class MySmmContactPerson_ContactPersonDs_Extension
    // Declare and initalize FormObservableLink
    private FormObservableLink observableLink = new FormObservableLink();
    edit NoYes myMethod(boolean _set, ContactPerson _contactPerson, NoYes _newValue)
        // This says that observableLink will be able to refresh myMethod()
    void refreshMethodsWhenSomethingHappened()
        // Here we trigger a refresh

‘is’ and ‘as’ operators with .NET types

I recently ran into an unfortunate limitation of .NET Interop from X++ (in D365FO).
I wanted to check if an X++ object is of a given type, nevertheless the type used for the variable declaration was a .NET interface. Here is an example:

using Microsoft.Dynamics.ApplicationSuite.FinancialManagement.Currency.Framework;
void demo(IExchangeRateProvider _provider)
    if (_provider is ExchangeRateProviderCBOE) {}

Exchange rate providers are X++ classing implementing IExchangeRateProvider interface and I wanted to check if the object I received was a particular provider (namely ExchangeRateProviderCBOE class or its child). Unfortunately this ended up with a compilation error:

The operand on the left side of the ‘is’ or ‘as’ operator must be a table, class, or form.

As I tested, neither managed interfaces nor managed classes (such as System.Object) can be used on the left side of ‘is’ and ‘as’ operators.

I solved the problem by using Type.IsAssignableFrom() method. Simply using the ‘is’ operator would be nicer, but this does the job too.

void demo(IExchangeRateProvider _provider)
    System.Object providerObj = _provider;
    if (providerObj.GetType().IsAssignableFrom(new ExchangeRateProviderCBOE().GetType())) {}

Note that the problem is only with the left side of the operators, e.g. when you want to check whether a managed type is this or that. Using the ‘is’ operator to check if an instance of an X++ class implements a managed interface works without problems.

Object obj = new ExchangeRateProviderCBOE();
if (obj is IExchangeRateProvider) {}