Dialogs are a way to prompt a user for information or to allow for customizations of feature behavior. For example, the Tools/Options dialog has individual pages that let the user control the behavior for features like themes, editors, and document tabs.
Get started
To get started, follow the create the project section in the Getting Started section.
Work with dialogs
This guide is designed to cover the top user scenarios when working with dialogs:
Creating a tool window with the new Extensibility Model is as simple as calling the ShowDialogAsync method from the ShellExtensibility helpers and passing in your dialog content.
ShowDialogAsync
The ShowDialogAsync method has several overloads that you should become familiar with:
publicoverrideasync Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Ownership of the RemoteUserControl is transferred to Visual Studio, so it shouldn't be disposed by the extension#pragmawarning disable CA2000 // Dispose objects before losing scopevar control = new MyDialogControl(null);
#pragmawarning restore CA2000 // Dispose objects before losing scopeawaitthis.Extensibility.Shell().ShowDialogAsync(control, cancellationToken);
}
For more information on creating a RemoteUserControl, see Remote UI.
Customize the dialog title
When your extension shows a dialog, you can provide a custom title string which will be displayed in the dialog's caption region.
C#
publicoverrideasync Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Ownership of the RemoteUserControl is transferred to Visual Studio, so it shouldn't be disposed by the extension#pragmawarning disable CA2000 // Dispose objects before losing scopevar control = new MyDialogControl(null);
#pragmawarning restore CA2000 // Dispose objects before losing scopeawaitthis.Extensibility.Shell().ShowDialogAsync(control, "My Dialog Title", cancellationToken);
}
Customize the dialog buttons
When a dialog is shown in the IDE, certain combinations of predefined dialog buttons and default actions can be selected. The predefined button and action combinations can be found in Microsoft.VisualStudio.RpcContracts.Notifications.DialogOption.
Additionally, you can create your own combination of buttons and default actions from:
publicenum DialogButton
{
// Hides all of the dialog buttons.
None,
// Shows a single close button.
Close,
// Shows a single OK button.
OK,
// Shows an OK and Cancel button.
OKCancel
}
publicenum DialogResult
{
// The dialog was closed via the System.Threading.CancellationToken or using an// action provided by the Microsoft.Visual Studio.RpcContracts.RemoteUI.IRemoteUserControl// content.
None,
// The user clicked the Close button.
Close,
// The user clicked the OK button.
OK,
// The user clicked the Cancel button, or clicked the nonclient close button, or// pressed the Esc key.
Cancel
}
Examples
Adding a cancel button:
C#
publicoverrideasync Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Ownership of the RemoteUserControl is transferred to Visual Studio, so it shouldn't be disposed by the extension#pragmawarning disable CA2000 // Dispose objects before losing scopevar control = new MyDialogControl(null);
#pragmawarning restore CA2000 // Dispose objects before losing scopeawaitthis.Extensibility.Shell().ShowDialogAsync(control, DialogOption.OKCancel, cancellationToken);
}
Having no dialog buttons:
C#
publicoverrideasync Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Ownership of the RemoteUserControl is transferred to Visual Studio, so it shouldn't be disposed by the extension#pragmawarning disable CA2000 // Dispose objects before losing scopevar control = new MyDialogControl(null);
#pragmawarning restore CA2000 // Dispose objects before losing scopeawaitthis.Extensibility.Shell().ShowDialogAsync(control, new DialogOption(DialogButton.None, DialogResult.None), cancellationToken);
}
Get the dialog result
If you need to know whether a user affirmatively closed a dialog or dismissed it, you can await the call to ShowDialogAsync, and it will return a Microsoft.VisualStudio.RpcContracts.Notifications.DialogResult, which represents the action taken by the user.
C#
publicoverrideasync Task ExecuteCommandAsync(IClientContext context, CancellationToken cancellationToken)
{
// Ownership of the RemoteUserControl is transferred to Visual Studio, so it shouldn't be disposed by the extension#pragmawarning disable CA2000 // Dispose objects before losing scopevar control = new MyDialogControl(null);
#pragmawarning restore CA2000 // Dispose objects before losing scope
DialogResult result = awaitthis.Extensibility.Shell().ShowDialogAsync(control, "My Dialog Title", DialogOption.OKCancel, cancellationToken);
if (result == DialogResult.OK)
{
// User clicked the OK button
}
}
Next steps
See the DialogSample sample for a full example of creating an extension with a dialog.
Learn how to build message extensions that allow users to interact with external services within their flow of work in Microsoft Teams and Microsoft 365 Copilot.