逐步解說:在執行階段更新功能區中的控制項

本逐步解說會示範如何在功能區載入 Office 應用程式之後,使用功能區物件模型更新功能區中的控制項。

**適用於:**本主題中的資訊適用於下列應用程式的文件層級專案和應用程式層級專案:Excel 2007 和 Excel 2010、InfoPath 2010、Outlook 2007 和 Outlook 2010、PowerPoint 2007 和 PowerPoint 2010、Project 2010、Visio 2010、Word 2007 和 Word 2010。如需詳細資訊,請參閱依 Office 應用程式和專案類型提供的功能

這個範例會從 Northwind 範例資料庫提取資料,並填入 Microsoft Office Outlook 中的下拉式方塊和功能表中。 您在這些控制項中選取的項目會自動填入欄位 (例如電子郵件訊息中的 [收件者] 和 [主旨]) 中。

這個逐步解說將說明下列工作:

  • 建立新的 Outlook 增益集專案。

  • 設計自訂功能區群組。

  • 將自訂群組加入至內建索引標籤。

  • 在執行階段更新功能區中的控制項。

注意事項注意事項

在下列指示的某些 Visual Studio 使用者介面項目中,您的電腦可能會顯示不同的名稱或位置: 您所擁有的 Visual Studio 版本和使用的設定決定了這些項目。 如需詳細資訊,請參閱 使用設定

必要條件

您需要下列元件才能完成此逐步解說:

-

包含 Microsoft Office 開發者工具的 Visual Studio 2010 版本。 如需詳細資訊,請參閱[設定電腦以開發 Office 方案](bb398242\(v=vs.100\).md)。
  • Microsoft Office Outlook 2007 或 Microsoft Outlook 2010 

建立新的 Outlook 增益集專案

首先,請建立 Outlook 增益集專案。

若要建立新的 Outlook 增益集專案

  1. 在 Visual Studio 中,建立名稱為 Ribbon_Update_At_Runtime 的 Outlook 2007 或 Outlook 2010 增益集專案。

  2. 選取 [新增專案] 對話方塊中的 [為方案建立目錄]。

  3. 將專案儲存到預設的專案目錄。

    如需詳細資訊,請參閱 HOW TO:在 Visual Studio 中建立 Office 專案

設定自訂功能區群組

當使用者撰寫新的郵件訊息時,就會出現這個範例中的功能區。 若要建立功能區的自訂群組,請先將功能區項目加入至專案,然後使用功能區設計工具來設計群組。 此自訂群組將協助您從資料庫提取名稱和訂單記錄,以產生後續要給客戶的郵件。

若要設計自訂群組

  1. 在 [專案] 功能表上按一下 [加入新項目]。

  2. 選取 [加入新項目] 對話方塊中的 [功能區 (視覺化設計工具)]。

  3. 將新功能區的名稱變更為 CustomerRibbon,然後按一下 [加入]。

    CustomerRibbon.cs 或 CustomerRibbon.vb 檔案會在功能區設計工具中開啟,並顯示預設索引標籤和群組。

  4. 按一下 [功能區設計工具] 予以選取。

  5. 在 [屬性] 視窗中,按一下 [RibbonType] 屬性旁邊的下拉式箭頭,然後按一下 [Microsoft.Outlook.Mail.Compose]。

    這樣一來,當使用者在 Outlook 中撰寫新郵件時,功能區就會跟著出現。

  6. 按一下功能區設計工具中的 [Group1] 加以選取。

  7. 在 [屬性] 視窗中,將 [標籤] 設定為 Customer Purchases。

  8. 從 [工具箱] 的 [Office 功能區控制項] 索引標籤,將 [ComboBox] 拖曳至 [Customer Purchases] 群組。

  9. 按一下 [ComboBox1] 予以選取。

  10. 在 [屬性] 視窗中,將 [標籤] 設定為 Customers。

  11. 從 [工具箱] 的 [Office 功能區控制項] 索引標籤,將 [Menu] 拖曳至 [Customer Purchases] 群組。

  12. 在 [屬性] 視窗中,將 [標籤] 設定為 Product Purchased。

  13. 將 [Dynamic] 設定為 true。

    這樣一來,您就可以在功能區載入至 Office 應用程式後的執行階段,將項目加入至功能表或從功能表移除項目。

將自訂群組加入至內建索引標籤

內建索引標籤是已在 Outlook 總管或偵測器之功能區上的索引標籤。 在此程序中,您會將自訂群組加入至內建索引標籤,然後指定自訂群組在索引標籤上的位置。

若要將自訂群組加入至內建索引標籤

  1. 按一下 [TabAddins (內建)] 索引標籤加以選取。

  2. 在 [屬性] 視窗中展開 [ControlId] 屬性,然後將 [OfficeId] 設定為 TabNewMailMessage。

    這樣會將 [Customer Purchases] 群組加入至出現在新郵件之功能區的 [訊息] 索引標籤中。

  3. 按一下 [Customer Purchases] 群組加以選取。

  4. 展開 [屬性] 視窗中的 [Position] 屬性,然後按一下 [PositionType] 屬性旁邊的下拉式箭頭,再按一下 [BeforeOfficeId]。

  5. 將 [OfficeId] 屬性設定為 GroupClipboard。

    這樣會將 [Customer Purchases] 群組置於 [訊息] 索引標籤中的 [剪貼簿] 群組之前。

建立資料來源

請使用 [資料來源] 視窗,將具型別資料集加入您的專案。

若要建立資料來源

  1. 在 [資料] 功能表上,請按一下 [加入新資料來源]。

    這樣會啟動 [資料來源組態精靈]。

  2. 選取 [資料庫],然後按 [下一步]。

  3. 選取 [資料集],然後按 [下一步]。

  4. 選取與 Northwind 範例 Microsoft SQL Server Compact 3.5 資料庫的資料連接,或使用 [新增連接] 按鈕加入新的連接。

  5. 在選取或建立連接後,請按 [下一步]。

  6. 按 [下一步] 儲存連接字串。

  7. 在 [選擇您的資料庫物件] 頁面上,展開 [資料表]。

  8. 選取下列每個資料表旁邊的核取方塊:

    1. Customers

    2. Order Details

    3. Orders

    4. 產品

  9. 按一下 [完成]。

在執行階段更新自訂群組中的控制項

請使用功能區物件模型執行下列工作:

  • 將客戶名稱加入至 [Customers] 下拉式方塊。

  • 將功能表和按鈕控制項加入至代表銷售訂單和售出產品的 [Products Purchased] 功能表。

  • 使用來自 [Customers] 下拉式方塊和 [Products Purchased] 功能表的資料,填入新郵件的 ToSubjectBody 欄位。

若要使用功能區物件模型更新自訂群組中的控制項

  1. 在 [專案] 功能表上,按一下 [加入參考]。

  2. 按一下 [加入參考] 對話方塊中的 [.NET] 索引標籤,然後選取 [System.Data.Linq] 組件,再按一下 [確定]。

    此組件包含支援使用 Language-Integrated Queries (LINQ) 的類別。 您將透過 LINQ 並使用來自 Northwind 資料庫的資料來填入自訂群組中的控制項。

  3. 按一下 [方案總管] 中的 CustomerRibbon.cs 或 CustomerRibbon.vb 加以選取。

  4. 在 [檢視] 功能表上,按一下 [程式碼]。

    功能區程式碼檔案隨即在程式碼編輯器中開啟。

  5. 在功能區程式碼檔的頂端加入下列陳述式。 這些陳述式可讓您方便存取 LINQ 命名空間和 Outlook 主要 Interop 組件 (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.NorthwindDataSetTableAdapters
    
    using System.Data.Linq;
    using System.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.NorthwindDataSetTableAdapters;
    
  6. 在 CustomerRibbon 類別內加入下列程式碼。 這個程式碼宣告您會用來儲存來自 Northwind 資料庫中 Customer、Orders、Order Details 和 Product 資料表之資訊的資料表和資料表配接器。

        'Declare the Northwind data set.
    
        Dim nwDataSet As NorthwindDataSet = New NorthwindDataSet()
    
        'Declare the data tables.
    
        Dim customerTable As NorthwindDataSet.CustomersDataTable
        Dim orderTable As NorthwindDataSet.OrdersDataTable
        Dim orderDetailsTable As NorthwindDataSet.Order_DetailsDataTable
        Dim productsTable As NorthwindDataSet.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.
    NorthwindDataSet nwDataSet = new NorthwindDataSet();
    
    //Declare the data tables.
    
    NorthwindDataSet.CustomersDataTable customerTable;
    NorthwindDataSet.OrdersDataTable orderTable;
    NorthwindDataSet.Order_DetailsDataTable orderDetailsTable;
    NorthwindDataSet.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. 將下列其中一個程式碼區塊加入至 CustomerRibbon 類別。 這個程式碼會加入三種 Helper 方法,這些方法會在執行階段建立功能區的控制項。

    如果您專案的目標是 .NET Framework 4,請加入下列程式碼。 

    
    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;
    }
    

    如果您專案的目標是 .NET Framework 3.5,請加入下列程式碼。

    
    Private Function CreateRibbonDropDownItem() As RibbonDropDownItem
        Return New RibbonDropDownItem()
    End Function
    
    Private Function CreateRibbonMenu() As RibbonMenu
        Return New RibbonMenu()
    End Function
    
    Private Function CreateRibbonButton() As RibbonButton
        Dim button As RibbonButton = New RibbonButton()
        AddHandler (button.Click), AddressOf Button_Click
        Return button
    End Function
    
    private RibbonDropDownItem CreateRibbonDropDownItem()
    {
        return new RibbonDropDownItem();
    }
    private RibbonMenu CreateRibbonMenu()
    {
        return new RibbonMenu();
    }
    private RibbonButton CreateRibbonButton()
    {
        RibbonButton button = new RibbonButton();
        button.Click += new EventHandler<RibbonControlEventArgs>(button_Click);
        return button;
    }
    
  8. 以下列程式碼取代 CustomerRibbon_Load 事件處理常式方法。 此程式碼使用 LINQ 查詢執行下列工作:

    • 使用 Northwind 資料庫中 20 位客戶的 ID 和名稱來填入 [Customers] 下拉式方塊。

    • 呼叫 PopulateSalesOrderInfo Helper 方法。 此方法會以屬於目前選取之客戶的銷售訂單編號來更新 [ProductsPurchased] 功能表。

        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. 將下列程式碼加入至 CustomerRibbon 類別。 此程式碼使用 LINQ 查詢執行下列工作:

    • 將子功能表加入至與目前選取客戶相關之每筆銷售訂單的 [ProductsPurchased] 功能表中。

    • 將按鈕加入至銷售訂單相關產品的每個子功能表中。

    • 將事件處理常式加入至每個按鈕中。

    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. 在 [方案總管] 中,按兩下功能區程式碼檔。

    功能區設計工具隨即開啟。

  11. 在功能區設計工具中,按兩下 [Customers] 下拉式方塊。

    功能區程式碼檔案會在程式碼編輯器中開啟,並會出現 ComboBox1_TextChanged 事件處理常式。

  12. 以下列程式碼取代 ComboBox1_TextChanged 事件處理常式。 這個程式碼會執行下列工作:

    • 呼叫 PopulateSalesOrderInfo Helper 方法。 此方法會以選取之客戶相關的銷售訂單來更新 [Products Purchased] 功能表。

    • 呼叫 PopulateMailItem Helper 方法,並傳入目前的文字 (即選取的客戶名稱)。 此方法會填入新郵件的 ToSubjectBody 欄位。

    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. 將下列 Click 事件處理常式加入至 CustomerRibbon 類別。 此程式碼會將選取產品的名稱加入至新郵件的 Body 欄位。

    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. 將下列程式碼加入至 CustomerRibbon 類別。 這個程式碼會執行下列工作:

    • 使用目前選取之客戶的電子郵件地址來填入新郵件的 To 行。

    • 將文字加入至新郵件的 SubjectBody 欄位。

    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: ";
    }
    

測試自訂群組中的控制項

當您在 Outlook 中開啟新郵件表單時,名為 [Customer Purchases] 的自訂群組會出現在功能區的 [訊息] 索引標籤中。

若要建立客戶的後續電子郵件訊息,請先選取客戶,再選取客戶所購買的產品。 在執行階段,[Customer Purchases] 群組中的控制項會以 Northwind 資料庫中的資料來更新。

若要測試自訂群組中的控制項

  1. 請按 F5 執行您的專案。

    Outlook 隨即啟動。

  2. 在 Outlook 的 [檔案] 功能表上,指向 [新增],然後按一下 [郵件]。

    這時會發生下列動作:

    • 新的郵件偵測器視窗會開啟。

    • 在功能區的 [訊息] 索引標籤上,[Customer Purchases] 群組會出現在 [剪貼簿] 群組的前面。

    • 群組中的 [Customers] 下拉式方塊會以 Northwind 資料庫中的客戶名稱來更新。

  3. 在功能區的 [訊息] 索引標籤上,於 [Customer Purchases] 群組的 [Customers] 下拉式方塊中選取客戶。

    這時會發生下列動作:

    • [Products Purchased] 功能表會更新,以顯示所選取客戶的每筆銷售訂單。

    • 每筆銷售訂單子功能表會更新,以顯示以該訂單購買的產品。

    • 選取的客戶電子郵件地址會加入至郵件的 [收件者] 行,並在郵件的主旨跟本文中填入文字。

  4. 按一下 [Products Purchases] 功能表,指向任何銷售訂單,然後按一下銷售訂單中的產品。

    產品名稱會加入至郵件的本文中。

後續步驟

您可以透過下列主題,進一步了解自訂 Office UI 的方式:

請參閱

工作

HOW TO:開始自訂功能區

逐步解說:使用功能區設計工具建立自訂的索引標籤

HOW TO:變更功能區索引標籤的位置

HOW TO:自訂內建索引標籤

HOW TO:自訂 Microsoft Office 功能表

HOW TO:將功能區設計工具的功能區匯出到功能區 XML

HOW TO:顯示增益集使用者介面錯誤

概念

在執行階段存取功能區

功能區設計工具

功能區物件模型概觀

自訂 Outlook 的功能區

其他資源

功能區概觀

Language-Integrated Query (LINQ)