Share via


Walkthrough: Creating an Options Page

This walkthrough creates two Tools Options pages, a simple page and a custom page. The simple page uses a property grid to examine and set properties, and the custom page provides its own user interface (UI). The managed package framework (MPF) supports both scenarios, with very little additional code.

To save these properties to and restore them from a settings file, follow these steps, and then see Walkthrough: Creating a Settings Category (C#).

The MPF provides two classes to help you create Tools Options pages, the Package class and the DialogPage class. You create a VSPackage to provide a container for these pages by subclassing the Package class. You create each tools options page by deriving from the DialogPage class.

In this walkthrough, you create the Tools Options pages and use them to display and change application options. You retrieve the option values from the hosting VSPackage. You retrieve them programmatically from another VSPackage by using Automation.

Creating a Tools Options Grid Page

In this section, you use the Visual Studio Integration Package wizard to create a simple Tools Options property grid. You use this grid to display and change the value of a property.

To create the VSPackage project

  1. Create a new Visual Studio Integration Package project named MyToolsOptions.

    For more information about how to create a managed VSPackage, see How to: Create VSPackages (C# and Visual Basic).

  2. On the Select a Programming Language page, select Visual Basic or Visual C#.

  3. On the Select VSPackage Options page, select Menu Command.

  4. On the Command Options page, change the Command name to Get internal option VB or Get internal option CS for Visual Basic or Visual C# respectively, and then click Finish.

To create the Tools Options property grid

  1. Open the MyToolsOptionsPackage file in the code editor.

  2. Add the following namespace references.

    Imports System.ComponentModel
    
    using System.ComponentModel;
    
  3. Declare an OptionsPageGrid class and derive it from DialogPage.

    Public Class OptionPageGrid
        Inherits DialogPage
    End Class
    
    public class OptionPageGrid : DialogPage
    {
    }
    
  4. Apply a System.Runtime.InteropServices.ClassInterfaceAttribute to the OptionPageGrid class:

    <ClassInterface(ClassInterfaceType.AutoDual)> _
    Public Class OptionPageGrid
    
    [ClassInterface(ClassInterfaceType.AutoDual)][CLSCompliant(false), ComVisible(true)]
    public class OptionPageGrid : DialogPage
    

    This creates a COM dual interface that lets Visual Studio Automation use GetAutomationObject to access the public members of the class programmatically.

  5. Apply a ProvideOptionPageAttribute to the VSPackage class to assign to the class an options category and options page name for the OptionPageGrid.

    <ProvideOptionPage(GetType(OptionPageGrid), _ 
        "My Category VB", "My Grid Page VB", 0, 0, True)> _ 
    Public NotInheritable Class MyToolsPotionsPackage
        Inherits Package
    
    [ProvideOptionPage(typeof(OptionPageGrid), 
        "My Category CS", "My Grid Page CS", 0, 0, true)] 
    public sealed class MyToolsOptionsCSPackage : Package
    

    Note

    You can localize the category and page name by assigning resource IDs to the attribute properties, CategoryResourceID, and PageNameResourceID, respectively.

  6. Add an OptionInteger property to the OptionPageGrid class.

    <ClassInterface(ClassInterfaceType.AutoDual)> _
    Public Class OptionPageGrid
        Inherits DialogPage
    
        Private optionValue As Integer= 256; 
    
        <Category("My Options VB")> _ 
        <DisplayName("My Option Integer VB")> _ 
        <Description("My integer option VB")> _ 
        Public Property OptionInteger() As Integer 
            Get 
                Return optionValue 
            End Get 
            Set(ByVal value As Integer) 
                optionValue = value 
            End Set 
        End Property
    End Class
    
    [ClassInterface(ClassInterfaceType.AutoDual)]
    public class OptionPageGrid : DialogPage
    {
        private int optionValue = 256; 
    
        [Category("My Options CS")] 
        [DisplayName("My Option Integer CS")] 
        [Description("My integer option CS")] 
        public int OptionInteger 
        { 
            get { return optionValue; } 
            set { optionValue = value; } 
        }
    }
    

    Note

    The default implementation of DialogPage supports properties that have appropriate converters or that are structures or arrays that can be expanded into properties that have appropriate converters. For a list of converters, see the System.ComponentModel namespace. The OptionsPage Sample (C#) manages int, string, and System.Drawing.Size properties.

  7. Build and start the project in debug mode by pressing F5. This starts Visual Studio in the experimental hive.

    Note

    Both versions of Visual Studio are open now.

  8. In Visual Studio Exp, on the Tools menu click Options.

    The Options dialog opens.

  9. In the tree view, expand My Category and then click My Grid Page.

    The options grid appears in the right pane. The property category is My Options, and the property name is MyOption Integer. The property description, My integer option, appears at the bottom of the pane.

    Change the value from its initial value of 256 to something else. Click OK, and then reopen My Grid Page. You can see that the new value persists.

  10. Exit Visual Studio Exp.

Creating a Tools Options Custom Page

In this section, you create a Tools Options page with a custom UI. You use this page to display and change the value of a property.

To create a Tools Options custom page

  1. Open the MyToolsOptionsPackage file in the code editor.

  2. Add the following namespace statement.

    Imports System.Windows.Forms
    
    using System.Windows.Forms;
    
  3. Add an OptionPageCustom class, just before the OptionPageGrid class. Derive the new class from DialogPage.

    Public Class OptionPageCustom
        Inherits DialogPage
    End Class
    
    public class OptionPageCustom : DialogPage
    {
    }
    
  4. On the Tools menu, click Create GUID to copy and paste a new GUID with registry format into the code, removing the braces. Add a System.Runtime.InteropServices.ClassInterfaceAttribute. Add the string property, OptionString. Note that your GUID will differ from the GUID in the example:

    [ClassInterface(ClassInterfaceType.AutoDual)]
    [Guid("42C7F4D9-200D-4fe2-A093-49AFA2DDE7F8")]
    Public Class OptionPageCustom
        Inherits DialogPage
    
        Private optionValue As String = "alpha";
    
        Public Property OptionString() As String
            Get
                return optionValue
            End Get
            Set(ByVal value As String)
                optionValue = value
            End Set
        End Property
    End Class
    
    [ClassInterface(ClassInterfaceType.AutoDual)]
    [Guid("1D9ECCF3-5D2F-4112-9B25-264596873DC9")]
    public class OptionPageCustom : DialogPage
    {
        private string optionValue = "alpha";
    
        public string OptionString
        {
            get { return optionValue; }
            set { optionValue = value; }
        }
    }
    
  5. Apply a ProvideOptionPageAttribute to the VSPackage class. This will assign the class an options category and options page name.

    <ProvideOptionPage(GetType(OptionPageCustom), _ 
        "My Category VB", "My Custom Page VB", 0, 0, True)> _ 
    <ProvideOptionPage(GetType(OptionPageGrid), _ 
        "My Category VB", "My Grid Page VB", 0, 0, True)> _ 
    Public NotInheritable Class MyToolsPotionsPackage
        Inherits Package
    
    [ProvideOptionPage(typeof(OptionPageCustom), 
        "My Category CS", "My Custom Page CS", 0, 0, true)] 
    [ProvideOptionPage(typeof(OptionPageGrid), 
        "My Category CS", "My Grid Page CS", 0, 0, true)] 
    public sealed class MyToolsOptionsCSPackage : Package
    
  6. Add a user control named MyUserControl to the project.

    The user control opens in Design view.

    Note

    If you see a warning, rebuild the solution and reopen MyUserControl.cs. This is a known issue.

  7. Add a TextBox control to the user control. In the Properties window, on the toolbar, click the Events button, and then double-click the Leave event.

    The code editor opens to show the new event handler.

  8. Add a public OptionsPage field, an Initialize method to the control class, and update the body of the event handler as follows:

    Imports System
    
    Public Class MyUserControl
    
        Friend optionsPage As OptionPageCustom 
    
        Public Sub Intitialize() 
            TextBox1.Text = optionsPage.OptionsSting 
        End Sub 
    
        Private Sub TextBox1_Leave( _ 
            (ByVal sender As Object, ByVal e As EventArges) _ 
            Handles TextBox1.Leave 
    
            optionsPage.OptionString = TextBox1.Text 
        End Sub
    End Class
    
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();
        }
    
        internal OptionPageCustom optionsPage; 
    
        public void Initialize() 
        { 
            textBox1.Text = optionsPage.OptionString; 
        } 
    
        private void textBox1_Leave(object sender, EventArgs e) 
        { 
            optionsPage.OptionString = textBox1.Text; 
        }
    }
    

    The optionsPage field holds a reference to the parent OptionPageCustom instance. The Initialize method displays OptionString in the TextBox. The event handler writes the current value of the TextBox to the OptionString when focus leaves the TextBox.

  9. In the package code file, add an override for the OptionPageCustom.Window property to the OptionPageCustom class to create, initialize, and return an instance of MyUserControl. Following is an example:

    Public Property OptionString() As String
        Get
            return optionValue
        End Get
        Set(ByVal value As String)
            optionValue = value
        End Set
    End Property
    
    <Browsable(false)> _ 
    <DesignerSerializationVisibility( 
        DesignerSerializationVisibility.Hidden)> _ 
    Protected Overrides ReadOnly Property Window() As IWin32Window 
        Get 
            Dim page As New MyUserControl() 
            page.optionsPage = Me 
            page.Initialize() 
            return page 
        End Get 
    End Property
    
    public string OptionString
    {
        get { return optionValue; }
        set { optionValue = value; }
    }
    
    [Browsable(false)] 
    [DesignerSerializationVisibility( 
        DesignerSerializationVisibility.Hidden)] 
    protected override IWin32Window Window 
    { 
        get 
        { 
            MyUserControl page = new MyUserControl(); 
            page.optionsPage = this; 
            page.Initialize(); 
            return page; 
        } 
    }
    
  10. Build and start the project in debug mode by pressing F5. This starts a new Visual Studio instance.

    Note

    Both versions of Visual Studio are open at this point.

  11. In the new Visual Studio instance, click the Tools menu and then click Options.

    The Options dialog opens.

  12. In the tree view in the left pane, expand My Category and then click My Custom Page.

  13. Change the value of OptionString from its initial value, alpha, to something else. Click OK, and then reopen My Custom Page. You can see that the new value has persisted.

  14. Close the new Visual Studio instance.

Accessing Options from the Hosting VSPackage

In this section, you obtain the value of an option from the VSPackage that hosts the associated Tools Options page. The same technique can be used to obtain the value of any public property.

To access an option from the hosting VSPackage

  1. In the package file, replace the body of the MyToolsOptions.MenuItemCallback method with the following lines:

    Private Sub MenuItemCallback(ByVal sender As Object, ByVal e As EventArgs)
        Dim page As OptionPageGrid = CType( _ 
            GetDialogPage(GetType(OptionPageGrid), OptionPageGrid) 
        MessageBox.Show(String.Format(CultureInfo.CurrentCulture, _ 
            "OptionInteger: {0}", page.OptionInteger))
    End Sub
    
    private void MenuItemCallback(object sender, EventArgs e)
    {
        OptionPageGrid page = 
            (OptionPageGrid)GetDialogPage(typeof(OptionPageGrid)); 
        MessageBox.Show(string.Format(CultureInfo.CurrentCulture, 
            "OptionInteger: {0}", page.OptionInteger));
    }
    

    This code calls GetDialogPage to create or retrieve an OptionPageGrid instance. OptionPageGrid in turn invokes LoadSettingsFromStorage to load its options, which are public properties.

  2. Build and start the project in debug mode by pressing the keyboard shortcut, F5. This starts a new instance of Visual Studio.

    Note

    Both versions of Visual Studio are open at this point.

  3. On the Tools menu, click Get internal option.

    A message box displays the current value of OptionInteger.

  4. Exit the new Visual Studio instance.

Accessing Options by using Automation

In this section, you use Automation to obtain the value of an option from any VSPackage or add-in. The same technique can be used to obtain the value of any public property.

To access an option using Automation

  1. Right-click the MyToolsOptions solution in Solution Explorer and add a new Visual Studio Integration Package project named AnotherPackage.

    For more information about how to create a managed VSPackage, see How to: Create VSPackages (C# and Visual Basic).

    The Package Wizard starts.

  2. In the Select a Programming Language page, select Visual Basic or Visual C#.

  3. In the Select VSPackage Options page, select Menu Command.

  4. In the Command Options page, change the Command Name to "Get external option", and then click Finish.

    The wizard creates the managed project, AnotherPackage.

  5. Right-click the AnotherPackage project node and then click Set as StartUp Project.

  6. Right-click the References node of the AnotherPackage project and then click Add Reference.

  7. Make sure the .NET tab is selected. Select EnvDTE (not envdte), and then click OK.

  8. Add the following namespace references to the these lines to the VsPkg code file in the AnotherPackage project:

    Imports EnvDTE
    Imports System.Windows.Forms
    
    using EnvDTE;
    using System.Windows.Forms;
    
  9. Replace the body of the AnotherPackage.MenuItemCallback method with the following lines:

    Private Sub MenuItemCallback(ByVal sender As Object, ByVal e As EventArgs)
        Dim env As DTE = CType(GetService(GetType(DTE)), DTE) 
    
        Dim props As EnvDTE.Properties = _ 
            env.Properties("My Category VB", "My Grid Page VB") 
    
        Dim value As Integer = CInt(props.Item("ObjectInteger").Value) 
        MessageBox.Show("OptionInteger: " & value.ToString())
    End Sub
    
    private void MenuItemCallback(object sender, EventArgs e)
    {
        DTE env = (DTE)GetService(typeof(DTE));  
    
        EnvDTE.Properties props = 
            env.get_Properties("My Category CS", "My Grid Page CS"); 
    
        int n = (int) props.Item("OptionInteger").Value; 
        MessageBox.Show("OptionInteger: " + n);
    }
    

    This code calls a service to obtain the DTE object, the root object of the Visual Studio Automation model. Properties returns the properties collection for My Category.MyGridPage, which includes all public properties. The Item method selects OptionInteger from the collection.

  10. Build and start the project in debug mode by pressing the keyboard shortcut, F5. This starts a new instance of Visual Studio.

    Note

    Both versions of Visual Studio are open at this point.

  11. On the Tools menu, click Get external option.

    A message box displays the current value of OptionInteger.

See Also

Concepts

Support for Options Pages

Other Resources

OptionsPage Sample (C#)

VSPackage State

Change History

Date

History

Reason

Added [CLSCompliant(false), ComVisible(true)]to fix wiki bug.

Content bug fix.