Partilhar via


Walkthrough: Updating the Controls on a Ribbon at Run Time

This walkthrough demonstrates how to use the Ribbon object model to update the controls on a Ribbon after the Ribbon is loaded into the Office application.

Applies to: The information in this topic applies to document-level projects and application-level projects for the following applications: Excel 2013 and Excel 2010; InfoPath 2013 and InfoPath 2010; Outlook 2013 and Outlook 2010; PowerPoint 2013 and PowerPoint 2010; Project 2013 and Project 2010; Visio 2013 and Visio 2010; Word 2013 and Word 2010. For more information, see Features Available by Office Application and Project Type.

The example pulls data from the Northwind sample database to populate a combo box and menu in Microsoft Office Outlook. Items that you select in these controls automatically populate fields such as To and Subject in an e-mail message.

This walkthrough illustrates the following tasks:

  • Creating a new Outlook add-in project.

  • Designing a custom Ribbon group.

  • Adding the custom group to a built-in tab.

  • Updating controls on the Ribbon at run time.

Note

Your computer might show different names or locations for some of the Visual Studio user interface elements in the following instructions. The Visual Studio edition that you have and the settings that you use determine these elements. For more information, see Customizing Development Settings in Visual Studio.

Prerequisites

You need the following components to complete this walkthrough:

Creating a New Outlook Add-in Project

First, create an Outlook add-in project.

To create a new Outlook add-in project

  1. In Visual Studio, create an Outlook 2010 or Outlook 2013 add-in project with the name Ribbon_Update_At_Runtime.

  2. In the New Project dialog box, select Create directory for solution.

  3. Save the project to the default project directory.

    For more information, see How to: Create Office Projects in Visual Studio.

Designing a Custom Ribbon Group

The Ribbon for this example will appear when a user composes a new mail message. To create a custom group for the Ribbon, first add a Ribbon item to your project, and then design the group in the Ribbon Designer. This custom group will help you generate follow-up e-mail messages to customers by pulling names and order histories from a database.

To design a custom group

  1. On the Project menu, click Add New Item.

  2. In the Add New Item dialog box, select Ribbon (Visual Designer).

  3. Change the name of the new Ribbon to CustomerRibbon, and then click Add.

    The CustomerRibbon.cs or CustomerRibbon.vb file opens in the Ribbon Designer and displays a default tab and group.

  4. Click the Ribbon Designer to select it.

  5. In the Properties window, click the drop-down arrow next to the RibbonType property, and then click Microsoft.Outlook.Mail.Compose.

    This enables the Ribbon to appear when the user composes a new mail message in Outlook.

  6. In the Ribbon Designer, click Group1 to select it.

  7. In the Properties window, set Label to Customer Purchases.

  8. From the Office Ribbon Controls tab of the Toolbox, drag a ComboBox onto the Customer Purchases group.

  9. Click ComboBox1 to select it.

  10. In the Properties window, set Label to Customers.

  11. From the Office Ribbon Controls tab of the Toolbox, drag a Menu onto the Customer Purchases group.

  12. In the Properties window, set Label to Product Purchased.

  13. Set Dynamic to true.

    This enables you to add and remove controls on the menu at run time after the Ribbon is loaded into the Office application.

Adding the Custom Group to a Built-in Tab

A built-in tab is a tab that is already on the Ribbon of an Outlook Explorer or Inspector. In this procedure, you will add the custom group to a built-in tab, and then specify the position of the custom group on the tab.

To add the custom group to a built-in tab

  1. Click the TabAddins (Built-In) tab to select it.

  2. In the Properties window, expand the ControlId property, and then set OfficeId to TabNewMailMessage.

    This adds the Customer Purchases group to the Messages tab of the Ribbon that appears in a new mail message.

  3. Click the Customer Purchases group to select it.

  4. In the Properties window, expand the Position property, click the drop-down arrow next to the PositionType property, and then click BeforeOfficeId.

  5. Set the OfficeId property to GroupClipboard.

    This positions the Customer Purchases group before the Clipboard group of the Messages tab.

Creating the Data Source

Use the Data Sources window to add a typed dataset to your project.

To create the data source

  1. On the Data menu, click Add New Data Source.

    This starts the Data Source Configuration Wizard.

  2. Select Database, and then click Next.

  3. Select Dataset, and then click Next.

  4. Select a data connection to the Northwind sample Microsoft SQL Server Compact 4.0 database, or add a new connection by using the New Connection button.

  5. After a connection has been selected or created, click Next.

  6. Click Next to save the connection string.

  7. On the Choose Your Database Objects page, expand Tables.

  8. Select the check box next to each of the following tables:

    1. Customers

    2. Order Details

    3. Orders

    4. Products

  9. Click Finish.

Updating Controls in the Custom Group at Run Time

Use the Ribbon object model to perform the following tasks:

  • Add customer names to the Customers combo box.

  • Add menu and button controls to the Products Purchased menu that represent sales orders and products sold.

  • Populate the To, Subject, and Body fields of new mail messages by using data from the Customers combo box and Products Purchased menu.

To update controls in the custom group by using the Ribbon object model

  1. On the Project menu, click Add Reference.

  2. In the Add Reference dialog box, click the .NET tab, select the System.Data.Linq assembly, and then click OK.

    This assembly contains classes for using Language-Integrated Queries (LINQ). You will use LINQ to populate controls in the custom group with data from the Northwind database.

  3. In Solution Explorer, click CustomerRibbon.cs or CustomerRibbon.vb to select it.

  4. On the View menu, click Code.

    The Ribbon code file opens in the Code Editor.

  5. Add the following statements to the top of the Ribbon code file. These statements provide easy access to LINQ namespaces and to the namespace of the Outlook primary interop assembly (PIA).

    Imports System.Data.Linq
    Imports System.Linq
    Imports System.Data.Linq.Mapping
    Imports System.Linq.Expressions
    Imports Outlook = Microsoft.Office.Interop.Outlook
    Imports Ribbon_Update_At_Runtime.Northwind40DataSetTableAdapters
    
    using System.Data.Linq;
    using System.Data.Linq.Mapping;
    using System.Linq.Expressions;
    using Outlook = Microsoft.Office.Interop.Outlook;
    using System.Data;
    using System.IO;
    using Ribbon_Update_At_Runtime.Northwind40DataSetTableAdapters;
    
  6. Add the following code inside the CustomerRibbon class. This code declares the data table and table adapters that you will use to store information from the Customer, Orders, Order Details, and Product tables of the Northwind database.

        'Declare the Northwind data set. 
    
        Dim nwDataSet As Northwind40DataSet = New Northwind40DataSet()
    
        'Declare the data tables. 
    
        Dim customerTable As Northwind40DataSet.CustomersDataTable
        Dim orderTable As Northwind40DataSet.OrdersDataTable
        Dim orderDetailsTable As Northwind40DataSet.Order_DetailsDataTable
        Dim productsTable As Northwind40DataSet.ProductsDataTable
    
        'Declare the data table adapters for each table. 
    
        Dim customersTableAdapter As CustomersTableAdapter = New CustomersTableAdapter()
        Dim ordersTableAdapter As OrdersTableAdapter = New OrdersTableAdapter()
        Dim detailsTableAdapter As Order_DetailsTableAdapter = New Order_DetailsTableAdapter()
        Dim productsTableAdapter As ProductsTableAdapter = New ProductsTableAdapter()
    
    //Declare the Northwind dataset.
    Northwind40DataSet nwDataSet = new Northwind40DataSet();
    
    //Declare the data tables.
    
    Northwind40DataSet.CustomersDataTable customerTable;
    Northwind40DataSet.OrdersDataTable orderTable;
    Northwind40DataSet.Order_DetailsDataTable orderDetailsTable;
    Northwind40DataSet.ProductsDataTable productsTable;
    
    //Declare the data table adapters for each table.
    
    CustomersTableAdapter customerTableAdapter = new CustomersTableAdapter();
    OrdersTableAdapter ordersTableAdapter = new OrdersTableAdapter();
    Order_DetailsTableAdapter detailsTableAdapter = new Order_DetailsTableAdapter();
    ProductsTableAdapter productsTableAdapter = new ProductsTableAdapter();
    
  7. Add the following block of code to the CustomerRibbon class. This code adds three helper methods that create controls for the Ribbon at runtime.

    Private Function CreateRibbonDropDownItem() As RibbonDropDownItem
        Return Me.Factory.CreateRibbonDropDownItem()
    End Function 
    
    Private Function CreateRibbonMenu() As RibbonMenu
        Return Me.Factory.CreateRibbonMenu()
    End Function 
    
    Private Function CreateRibbonButton() As RibbonButton
        Dim button As RibbonButton = Me.Factory.CreateRibbonButton()
        AddHandler (button.Click), AddressOf Button_Click
        Return button
    End Function
    
    private RibbonDropDownItem CreateRibbonDropDownItem()
    {
        return this.Factory.CreateRibbonDropDownItem();
    }
    private RibbonMenu CreateRibbonMenu()
    {
        return this.Factory.CreateRibbonMenu();
    }
    private RibbonButton CreateRibbonButton()
    {
        RibbonButton button = this.Factory.CreateRibbonButton();
        button.Click += new RibbonControlEventHandler(button_Click);
        return button;
    }
    
  8. Replace the CustomerRibbon_Load event handler method with the following code. This code uses a LINQ query to perform the following tasks:

    • Populate the Customers combo box by using the ID and name of 20 customers in the Northwind database.

    • Calls the PopulateSalesOrderInfo helper method. This method updates the ProductsPurchased menu with sales order numbers that pertain to the currently selected customer.

    Private Sub CustomerRibbon_Load(ByVal sender As System.Object, _
       ByVal e As Microsoft.Office.Tools.Ribbon.RibbonUIEventArgs) _
           Handles MyBase.Load
    
            customerTable = nwDataSet.Customers
            customersTableAdapter.Fill(customerTable)
    
            Dim customerQuery = From customers In customerTable.AsEnumerable.Take(20) _
                    Select CustomerID = customers.Customer_ID, _
                    CustomerName = customers.Contact_Name
    
            ' Execute the query. 
            For Each item In customerQuery
                Me.ComboBox1.Items.Add(CreateRibbonDropDownItem())
    
                Me.ComboBox1.Items.Last().Label = item.CustomerID.ToString() _
                    + "|" + item.CustomerName
            Next item
    
            Me.ComboBox1.Text = Me.ComboBox1.Items.First().Label
            PopulateSalesOrderInfo()
        End Sub
    
    private void CustomerRibbon_Load(object sender, RibbonUIEventArgs e)
    {
        customerTable = nwDataSet.Customers;
        customerTableAdapter.Fill(customerTable);
    
        var customerQuery = from customers in customerTable.AsEnumerable().Take(20)
                            select new
                            {
                                CustomerID = customers.Field<string>("Customer ID"),
                                CustomerName = customers.Field<string>("Contact Name")
                            };
    
    
        // Execute the query. 
        foreach (var item in customerQuery)
        {
            this.comboBox1.Items.Add(CreateRibbonDropDownItem());
            this.comboBox1.Items.Last().Label =
            item.CustomerName + "|" + item.CustomerID.ToString();
        }
        this.comboBox1.Text = this.comboBox1.Items.First().Label;
        PopulateSalesOrderInfo();
    }
    
  9. Add the following code to the CustomerRibbon class. This code uses LINQ queries to perform the following tasks:

    • Adds a submenu to the ProductsPurchased menu for each sales order related to the selected customer.

    • Adds buttons to each submenu for the products related to the sales order.

    • Adds event handlers to each button.

    Private Sub PopulateSalesOrderInfo()
    
        Dim tempArray As [String]() = comboBox1.Text.Split(New [Char]() {"|"c})
        Menu1.Items.Clear()
    
        orderTable = nwDataSet.Orders
        orderDetailsTable = nwDataSet.Order_Details
        productsTable = nwDataSet.Products
    
        ordersTableAdapter.Fill(orderTable)
        detailsTableAdapter.Fill(orderDetailsTable)
        productsTableAdapter.Fill(productsTable)
    
        Dim orderQuery = From order In orderTable.AsEnumerable() _
                         Where order.Customer_ID.ToString() = tempArray(0) _
                         Select New With {.SalesOrderID = order.Order_ID}
    
        For Each orderItem In orderQuery
            Me.Menu1.Items.Add(CreateRibbonMenu())
    
            Dim orderMenu As RibbonMenu = CType(Menu1.Items.Last(), RibbonMenu)
            orderMenu.Dynamic = True
            orderMenu.Label = orderItem.SalesOrderID.ToString()
            orderMenu.Tag = orderItem.SalesOrderID
    
            Dim productQuery = From orderDetail In orderDetailsTable.AsEnumerable(), _
                                   product In productsTable.AsEnumerable() _
                               Where orderDetail.Product_ID = _
                                   product.Product_ID _
                               And orderDetail.Order_ID = _
                               orderMenu.Tag _
            Select productName = product.Product_Name
    
            For Each productItem In productQuery
                Dim button As RibbonButton = CreateRibbonButton()
                button.Label = productItem
                orderMenu.Items.Add(button)
            Next productItem
        Next orderItem
    End Sub
    
    private void PopulateSalesOrderInfo()
    {
        String[] tempArray = comboBox1.Text.Split(new Char[] { '|' });
        menu1.Items.Clear();
    
        orderTable = nwDataSet.Orders;
        orderDetailsTable = nwDataSet.Order_Details;
        productsTable = nwDataSet.Products;
    
        ordersTableAdapter.Fill(orderTable);
        detailsTableAdapter.Fill(orderDetailsTable);
        productsTableAdapter.Fill(productsTable);
    
        var orderQuery = from orders in orderTable.AsEnumerable()
                         where orders.Field<string>("Customer ID") == tempArray[1]
                         select new { OrderID = orders.Field<int>("Order ID") };
    
        foreach (var orderItem in orderQuery)
        {
            menu1.Items.Add(CreateRibbonMenu());
    
            RibbonMenu orderMenu = (RibbonMenu)menu1.Items.Last();
            orderMenu.Dynamic = true;
            orderMenu.Label = orderItem.OrderID.ToString();
            orderMenu.Tag = orderItem.OrderID;
    
            var productQuery = from orderDetail in orderDetailsTable.AsEnumerable()
                               join product in productsTable.AsEnumerable() on
                                   orderDetail.Field<int>("Product ID")
                               equals product.Field<int>("Product ID")
                               where orderDetail.Field<int>("Order ID") ==
                                   orderItem.OrderID
                               select new { ProductName = product.Field<string>("Product Name") };
    
            foreach (var productItem in productQuery)
            {
                RibbonButton button = CreateRibbonButton();
                button.Label = productItem.ProductName;
                orderMenu.Items.Add(button);
            }
        }
    }
    
  10. In Solution Explorer, double-click the Ribbon code file.

    The Ribbon Designer opens.

  11. In the Ribbon Designer, double-click the Customers combo box.

    The Ribbon code file opens in the Code Editor, and the ComboBox1_TextChanged event handler appears.

  12. Replace the ComboBox1_TextChanged event handler with the following code. This code performs the following tasks:

    • Calls the PopulateSalesOrderInfo helper method. This method updates the Products Purchased menu with sales orders that relate to the selected customer.

    • Calls the PopulateMailItem helper method and passes in the current text, which is the selected customer name. This method populates the To, Subject, and Body fields of new mail messages.

    Private Sub ComboBox1_TextChanged(ByVal sender As System.Object, _
        ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs) _
            Handles ComboBox1.TextChanged
        PopulateSalesOrderInfo()
        PopulateMailItem(ComboBox1.Text)
    End Sub
    
    private void comboBox1_TextChanged(object sender,
        RibbonControlEventArgs e)
    {
        PopulateSalesOrderInfo();
        PopulateMailItem(comboBox1.Text);
    }
    
  13. Add the following Click event handler to the CustomerRibbon class. This code adds the name of selected products to the Body field of new mail messages.

    Private Sub Button_Click(ByVal sender As System.Object, _
        ByVal e As Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs)
        Dim application As Outlook.Application = Globals.ThisAddIn.Application
        Dim inspector As Outlook.Inspector = application.ActiveInspector()
        Dim myMailItem As Outlook.MailItem = CType(inspector.CurrentItem,  _
            Outlook.MailItem)
        Dim myButton As RibbonButton = CType(sender, RibbonButton)
        myMailItem.Subject = "Following up on your order"
        myMailItem.Body = myMailItem.Body + ControlChars.Lf + "* " _
            + myButton.Label
    End Sub
    
    void button_Click(object sender, RibbonControlEventArgs e)
    {
        Outlook.Application application = Globals.ThisAddIn.Application;
        Outlook.Inspector inspector = application.ActiveInspector();
        Outlook.MailItem myMailItem = (Outlook.MailItem)inspector.CurrentItem;
        RibbonButton myCheckBox = (RibbonButton)sender;
        myMailItem.Subject = "Following up on your order";
        myMailItem.Body = myMailItem.Body + "\n" + "* " + myCheckBox.Label;
    }
    
  14. Add the following code to the CustomerRibbon class. This code performs the following tasks:

    • Populates the To line of new mail messages by using the e-mail address of the currently selected customer.

    • Adds text to the Subject and Body fields of new mail messages.

    Private Sub PopulateMailItem(ByVal addressToLine As String)
        Dim application As Outlook.Application = Globals.ThisAddIn.Application
        Dim inspector As Outlook.Inspector = application.ActiveInspector()
        Dim myMailItem As Outlook.MailItem = _
            CType(inspector.CurrentItem, Outlook.MailItem)
    
        myMailItem.To = "" 
        Dim tempArray As [String]() = addressToLine.Split(New [Char]() {"|"c})
        myMailItem.To = tempArray(1) + "@example.com"
        myMailItem.Subject = "Following up on your order"
        myMailItem.Body = "Hello " + tempArray(1) + "," _
            + ControlChars.Lf + "We would like to get your feedback" + _
            "on the following products that you recently ordered: " 
    End Sub
    
    private void PopulateMailItem(string addressToLine)
    {
        Outlook.Application application = Globals.ThisAddIn.Application;
        Outlook.Inspector inspector = application.ActiveInspector();
        Outlook.MailItem myMailItem = (Outlook.MailItem)inspector.CurrentItem;
    
        myMailItem.To = "";
        String[] tempArray = addressToLine.Split(new Char[] { '|' });
        myMailItem.To = tempArray[0] + "@example.com";
        myMailItem.Subject = "Following up on your order";
        myMailItem.Body = "Hello " + tempArray[0] + "," +
            "\n" + "We would like to get your feedback on the " +
            "following products that you recently ordered: ";
    }
    

Testing the Controls in the Custom Group

When you open a new mail form in Outlook, a custom group named Customer Purchases appears on the Messages tab of the Ribbon.

To create a customer follow-up e-mail message, select a customer, and then select products purchased by the customer. The controls in the Customer Purchases group are updated at run time with data from the Northwind database.

To test the controls in the custom group

  1. Press F5 to run your project.

    Outlook starts.

  2. In Outlook, on the File menu, point to New, and then click Mail Message.

    The following actions occur:

    • A new mail message Inspector window appears.

    • On the Message tab of the Ribbon, the Customer Purchases group appears before the Clipboard group.

    • The Customers combo box in the group is updated with the names of customers in the Northwind database.

  3. On the Message tab of the Ribbon, in the Customer Purchases group, select a customer from the Customers combo box.

    The following actions occur:

    • The Products Purchased menu is updated to show each sales order for the selected customer.

    • Each sales order submenu is updated to show the products purchased in that order.

    • The selected customer's e-mail address is added to the To line of the mail message, and the subject and body of the mail message are populated with text.

  4. Click the Products Purchases menu, point to any sales order, and then click a product from the sales order.

    The product name is added to the body of the mail message.

Next Steps

You can learn more about how to customize the Office UI from these topics:

See Also

Tasks

How to: Get Started Customizing the Ribbon

Walkthrough: Creating a Custom Tab by Using the Ribbon Designer

How to: Change the Position of a Tab on the Ribbon

How to: Customize a Built-in Tab

How to: Add Controls to the Backstage View

How to: Export a Ribbon from the Ribbon Designer to Ribbon XML

How to: Show Add-in User Interface Errors

Concepts

Accessing the Ribbon at Run Time

Ribbon Designer

Ribbon Object Model Overview

Customizing a Ribbon for Outlook

Other Resources

Ribbon Overview

Language-Integrated Query (LINQ)