Visual Studio 2017 Extension development tutorial, Part 4: Show a popup Window

Tutorial Table of Contents:

Part 1: Introduction to VS extensibility
Part 2: Add Menu Item
Part 3: Add command to context menu and get selected code
Part 5: Highlight code in Editor
part 6: Follow a span of code with TrackingSpan
Part 7: Insert buttons between text characters with Adornments
Part 8: Add UI in the indicator margin with Glyphs

During the tutorial we are going to build a VS extensions called CodyDocs and place it on GitHub. Each tutorial part is a standalone tutorial on a specific topic and can be viewed individually. CodyDocs will save code documentation in a separate file and the extension will allow to view and edit the documentation in the editor itself.

Part 4: Show a popup Window

In the previous part we created a Command that appears in the code editor’s context menu.

Let’s place our logic to run on our command’s callback:

ShowAddDocumentationWindow is the only line relevant to this part of the tutorial.

To show our own custom popup window, Microsoft recommends using DialogWindow, which is what we will do. This is a WPF window which allows you to act as a modal dialog. Which means the popup blocks the rest of Visual Studio UI until closed.

First, to use WPF we will need these references:

  • PresentationCore
  • PresentationFramework
  • WindowsBase
  • System.Xaml

System.Xaml is probably the only thing missing from the regular VSIX template project. To add it, right click on the project -> Add -> Reference and choose System.Xaml.

 

Create a DialogWindow

For some reason, we can’t add a new DialogWindow item to our project directly. It doesn’t exist in the New Item dialog. There’s an easy way to get over this obstacle though.

First, we need to create a BaseDialogWindow class we can use for all our popup windows:

Now we need to create our custom window with XAML and code behind that we can edit. There’s a little trick we need to use so we can have our .xaml file next to our .xaml.cs file. First, add a new UserControl item to the project. Let’s call it AddDocumentationWindow. We’re calling it a Window because it will become that real soon.

The user control initially looks like this:

In .xaml.cs:

Now let’s change it to a Window. It should inherit BaseDialogWindow, so in .xaml, UserControl should change to BaseDialogWindow:

The .xaml.cs file remains unchanged.

That’s it. Now you can edit the XAML and code behind as needed.

Show the popup Dialog Window

To show the dialog, create an instance of the Dialog Window and call ShowDialog:

Popup window in CodyDocs

As mentioned before, we’re building an extension called CodyDocs as part of this tutorial. I added code that shows a popup window from our context menu command “Add documentation”. Here’s how it looks:

The code is available on GitHub. To checkout to the extension code right after adding the popup window, use the Tag Part4:

Summary

In this part, we saw how to show a popup dialog window with a Visual Studio extension. I’ll admit it’s not the most intuitive thing in the world, but not too hard either.

In following tutorial parts, we’ll see how to show adorners (heads up display) in the code editor. A bit further on, I also plan to get into Roslyn, the C# compiler that allows us to analyze and rewrite code.

 

Share:

Enjoy the blog? I would love you to subscribe! Performance Optimizations in C#: 10 Best Practices (exclusive article)

Want to become an expert problem fixer? Check out a chapter from my book Practical Debugging for .NET Developers

11 thoughts on “Visual Studio 2017 Extension development tutorial, Part 4: Show a popup Window”

  1. Learned a lot from this tutorial and a good place to start coding extensions. However the show pop section doesnt work in my version of VS 2017, version 15.5.4. I get invalid markup in the xaml and in the error list i get… The name “BaseDialogWindow” does not exist in the namespace “clr-namespace:CodyDocs”. Unless im missing something!

    1. Hi Dennis.
      The namespace of your BaseDialogWindow.cs file is probably not CodyDocs. Try changing the namespace to CodyDocs. Or alternatively, change the namespace in XAML to the same namespace as your BaseDialogWindow.

    2. Hello Dennis,
      I had the same issue, they were both in namespace CodyDocs, but changing BaseDialogWindow’s namespace to a different namespace fixed it

      Just change it to for example “Dialog”
      Then in AddDocumentationWindow.xaml add namespace reference inside opening tag of the user control ” xmlns:base=”clr-namespace:Dialog” ”
      And finally redefine wpf control as

      Hope this fixes it for you!

    3. You can actually just use DialogWindow.

      <ui:DialogWindow …
      xmlns:ui="clr-namespace:Microsoft.VisualStudio.PlatformUI;assembly=Microsoft.VisualStudio.Shell.14.0"

      Change the version as required.

  2. Hey,

    Great tutorial, but I always get an exception in the member fucntion GetSelection.

    The textManager is null and when it tries to get the activeView there’s an exception.

    I even tried with your code from Github and it has the same problem.

    Task service = serviceProvider.GetServiceAsync( typeof ( SVsTextManager ) );
    IVsTextManager2 textManager = service as IVsTextManager2;
    IVsTextView view;
    int result = textManager.GetActiveView2(1, null, (uint)_VIEWFRAMETYPE.vftCodeWindow, out view );

    1. Hi,

      I ran in to the same issue. Since the methods are Async you’ll have to cast the .Result:

      var textManager = service.Result as IVsTextManager2;

  3. I suggest some corrections:
    – “System.Xaml is probably the only thing missing from the regular VSIX template project”.
    On VS 2017, the 4 DLL have to be referenced.
    – “The .xaml.cs file remains unchanged.”
    As VS complains, we have to change it to: “public partial class AddDocumentationWindow : BaseDialogWindow”
    – “ShowAddDocumentationWindow()” should be completed by 2 parameters.
    Example:
    private void ShowAddDocumentationWindow(string docPath, TextViewSelection selection)
    {
    var documentationControl = new AddDocumentationWindow();
    documentationControl.SourceFile.Content = docPath;
    documentationControl.Selection.Content =
    string.Format(“From ({0},{1}) to ({2},{3})”,selection.StartPosition.Column, selection.StartPosition.Line, selection.EndPosition.Column, selection.EndPosition.Line);
    documentationControl.ShowDialog();
    }
    – The Xaml should be completed accordingly.
    Example:

    Source file:

    Selection:

  4. I’m trying to create a popup window for a different extension using this method. I’m getting an error of ” The name “BaseDialogWindow” does not exist in the namespace “clr-namespace:ProjectName.Dialogs” i’ve changed everything to use the same namespace yet im still getting the error. Any idea why?

Comments are closed.