操作方法:使用 InfoPath 2003 物件模型新增事件處理常式
在與 InfoPath 2003 物件模型相容的表單範本專案中,用於新增事件處理常式函式的功能表命令,基本上與使用指令碼的功能表命令相同。例如,若要新增 OnLoad 事件處理常式,請在以 InfoPath 設計模式所開啟的表單中,指向 [工具] 功能表的 [程式設計],然後按一下 [On Load 事件]。焦點便會自動切換至 Microsoft Visual Studio Tools for Applications (VSTA) 或 Microsoft Visual Studio 程式碼編輯器中 OnLoad 事件處理常式的表單程式碼。
在 Managed 程式碼表單範本專案中,包含事件處理常式函數的類別以及事件處理常式本身將以程式碼模組中 InfoPath 特定的屬性識別。
下列所有程序都假設您已經在具有 Microsoft Visual Studio Tools for Applications (VSTA) 的 Microsoft Office InfoPath 2007、具有 Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office system 的 Visual Studio 2005,或是 Visual Studio 2008 附 Visual Studio Tools for Office 中開啟表單範本專案。
為命令按鈕的 OnClick 事件新增事件處理常式
在 Visual Studio [工具箱] 的 [控制項] 工作窗格中,按一下 [按鈕],將一個按鈕新增至表單。
按兩下按鈕,然後按一下 [編輯表單程式碼]。
焦點會切換至程式碼編輯器中 OnClick 事件之事件處理常式的 Stub。
為欄位或群組的 OnBeforeChange、OnValidate 或 OnAfterChange 事件新增事件處理常式
以滑鼠右鍵按一下與欄位或群組繫結的資料輸入控制項,例如 [文字方塊] 控制項。
指向 [程式設計],然後按一下 [On Validate 事件]。
焦點會切換至程式碼編輯器中下列其中一個事件之事件處理常式的 Stub:OnBeforeChange、OnValidate 或 OnAfterChange。
注意
如果您是在 Visual Studio 中進行作業並將事件處理常式新增至欄位或群組,接著在 InfoPath [資料來源] 工作窗格中變更資料來源的結構描述,進而影響了欄位或群組 (例如,重新命名或移動),則當您切換回到 Visual Studio 時,便會顯示下列訊息:「您已變更表單範本的結構描述,可能需要更新表單程式碼中的 XPath 運算式。要自動更新這些運算式嗎?」。請一律按 [是],如此一來,用來將事件處理常式與欄位或群組關聯的 XPath 運算式,都會自動更新以反映變更。如果您按一下 [否],則必須自行更新事件處理常式之 InfoPathEventHandler 屬性的 MatchPath 參數中的 XPath 運算式,以防止事件處理常式失敗。如需詳細資訊,請參閱本主題稍後的「識別事件處理常式的方法」。
注意
另外請注意當您在 InfoPath 的 [資料來源] 工作窗格中變更結構描述時,會自動儲存這些變更,並在切換回 Visual Studio 時不提示即覆寫現有的表單範本。
為表單的 OnLoad、OnSwitchView、OnContextChange 或 OnSign 事件新增事件處理常式
在 [工具] 功能表中,指向 [程式設計],然後按一下要撰寫其事件處理常式的表單事件。
焦點會切換至程式碼編輯器中下列其中一項之事件處理常式的 Stub:OnLoad、OnSwitchView、OnContextChange 或 OnSign。
為表單的 OnSubmitRequest 事件新增事件處理常式
在 [工具] 功能表上,按一下 [送出選項]。
選取 [允許使用者送出這個表單] 核取方塊,然後按一下 [使用程式碼執行自訂動作]。
按一下 [編輯程式碼],再按一下 [確定]。
焦點會切換至程式碼編輯器中 OnSubmitRequest 事件之事件處理常式的 Stub。
為表單的 OnSaveRequest 事件新增事件處理常式
按一下 [工具] 功能表上的 [表單選項]。
在 [開啟和儲存] 類別中,按一下 [使用自訂程式碼儲存],再按一下 [編輯]。
焦點會切換至程式碼編輯器中 OnSaveRequest 事件之事件處理常式的 Stub。
為表單的 OnVersionUpgrade 事件新增事件處理常式
按一下 [工具] 功能表上的 [表單選項]。
在 [版本設定] 類別中,選取 [於版本升級] 清單的 [使用自訂事件],然後按一下 [編輯]。
焦點會切換至程式碼編輯器中 OnVersionUpgrade 事件之事件處理常式的 Stub。
為表單的 OnMergeRequest 事件新增事件處理常式
按一下 [工具] 功能表上的 [表單選項]。
在 [進階] 類別中,選取 [啟用表單合併] 與 [使用自訂程式碼進行合併] 核取方塊,然後按一下 [編輯]。
焦點會切換至程式碼編輯器中 OnMergeRequest 事件之事件處理常式的 Stub。
為 OnAfterImport 事件新增事件處理常式
若要為 OnAfterImport 事件新增事件處理常式,您必須開啟 Managed 程式碼表單範本的表單程式碼,並以手動方式新增事件處理常式函式。如需如何為這個事件撰寫事件處理常式的資訊,請按一下 OnAfterImport 事件的連結。
為次要資料來源新增事件處理常式
下列範例顯示如何為次要資料來源新增事件處理常式。本範例假設次要資料來源是從名為 books.xml 的資源檔案取得,該檔案具有下列結構描述:
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="catalog">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="book" minOccurs="0" maxOccurs="unbounded"></xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="genre" type="xsd:string"></xsd:element>
<xsd:element name="author" type="xsd:string"></xsd:element>
<xsd:element name="book">
<xsd:complexType>
<xsd:all>
<xsd:element ref="author" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element ref="title" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element ref="genre" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element ref="price" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element ref="publish_date" minOccurs="0" maxOccurs="1"></xsd:element>
<xsd:element ref="description" minOccurs="0" maxOccurs="1"></xsd:element>
</xsd:all>
<xsd:attribute ref="id"></xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="price" type="xsd:string"></xsd:element>
<xsd:element name="title" type="xsd:string"></xsd:element>
<xsd:element name="publish_date" type="xsd:string"></xsd:element>
<xsd:element name="description" type="xsd:string"></xsd:element>
<xsd:attribute name="id" type="xsd:string"></xsd:attribute>
</xsd:schema>
表單的檢視是從此資料來源所建立。表單程式碼會依據作者以及其已撰寫的書籍數量,建立一個雜湊資料表。您可以從檢視所顯示的表格來更新項目,OnAfterChange 事件處理常式便會更新雜湊資料表。請注意,用來參照次要資料來源的是 InfoPathEventHandler 屬性 (Attribute) 的 DataObject 屬性 (Property),這是由 InfoPathEventHandlerAttribute 類別所實作的。
namespace AuxDom
{
// InfoPathNamespace attribute goes here.
public class AuxDom
{
private XDocument thisXDocument;
private Application thisApplication;
private Hashtable authors;
public void _Startup(Application app, XDocument doc)
{
thisXDocument = doc;
thisApplication = app;
authors = new Hashtable();
}
public void _Shutdown()
{
authors.Clear();
}
// The following function handler is created by Microsoft
// Office InfoPath. Do not modify the type or number of
// arguments.
[InfoPathEventHandler(EventType=InfoPathEventType.OnLoad)]
public void OnLoad(DocReturnEvent e)
{
IXMLDOMDocument books = thisXDocument.GetDOM("books");
DOMNodeList externalAuthors = books.selectNodes("/catalog/book/author");
foreach (IXMLDOMNode authorNode in externalAuthors)
{
AddBookFromAuthor(authorNode.text);
}
}
// The following function handler is created by Microsoft
// Office InfoPath. Do not modify the type or number of
// arguments.
[InfoPathEventHandler(MatchPath="/catalog/book/author", EventType=InfoPathEventType.OnAfterChange, DataObject="books")]
public void books__author_OnAfterChange(DataDOMEvent e)
{
if (e.IsUndoRedo)
{
// An undo or redo operation has occurred and the DOM
// is read-only.
return;
}
if (e.Source.text != e.NewValue.ToString())
{
RemoveBookFromAuthor(e.OldValue.ToString());
AddBookFromAuthor(e.NewValue.ToString());
}
}
private void AddBookFromAuthor(string authorName)
{
if (authors.Contains(authorName))
{
authors[authorName] = (int)authors[authorName] + 1;
}
else
{
authors.Add(authorName, 1);
}
}
private void RemoveBookFromAuthor(string authorName)
{
if (authors.Contains(authorName))
{
authors[authorName] = (int)authors[authorName] - 1;
}
if ((int)authors[authorName] == 0)
{
authors.Remove(authorName);
}
}
// The following function handler is created by Microsoft
// Office InfoPath. Do not modify the type or number of
// arguments.
[InfoPathEventHandler(MatchPath="ShowAuthors", EventType=InfoPathEventType.OnClick)]
public void ShowAuthors_OnClick(DocActionEvent e)
{
// Write your code here.
StringBuilder report = new StringBuilder();
foreach (string authorName in authors.Keys)
{
report.Append(authorName + ",\t\t\t");
report.Append(authors[authorName] + "\n");
}
thisXDocument.UI.Alert(report.ToString());
}
}
}
如何識別包含事件處理常式的類別
當您建立相容於 InfoPath 2003 Managed 程式碼物件模型的新 InfoPath 表單範本專案時,便會將組件層級的 System.ComponentModel.Description 屬性套用至表單程式碼模組開頭的類別,以識別包含表單範本之所有事件處理常式的類別。
重要
請勿修改此類別中的 System.ComponentModel.Description 屬性。如果您這麼做,表單範本將無法識別事件處理常式所在的位置,而事件處理常式將無法執行。
using System;
using Microsoft.Office.Interop.InfoPath.SemiTrust;
// Office integration attribute. Identifies the startup class for the // form. Do not modify.
[assembly: System.ComponentModel.DescriptionAttribute( "InfoPathStartupClass, Version=1.0, Class=Template1.FormCode")]
Imports System
Imports Microsoft.Office.Interop.InfoPath.SemiTrust
' Office integration attribute. Identifies the startup class for the form. Do not modify.
<Assembly: System.ComponentModel.DescriptionAttribute( _ "InfoPathStartupClass, Version=1.0, Class=Template1.FormCode")>
識別事件處理常式的方法
當您在 InfoPath 設計模式使用者介面中使用功能表命令或按鈕來新增新事件處理常式時,便會將事件處理常式函式的 Stub 寫入表單。下列範例顯示替名為 'total' 的欄位新增的 OnValidate 所建立的 Stub 事件處理常式。
[C#]
[InfoPathEventHandler(MatchPath="/invoice/total", EventType=InfoPathEventType.OnValidate)]
public void total_OnValidate(DataDOMEvent e)
{
// Write your code here.
}
[Visual Basic]
<InfoPathEventHandler(MatchPath:="/invoice/total",EventType:= OnValidate)> Public Sub total_OnValidate(ByVal e As EventArgs)
' Write your code here.
End Sub
接著您可以新增程式碼,使用 thisXDocument
或 thisApplication
變數的私人快取成員來叫用 InfoPath 物件模型的成員,或使用從 e
EventArgs 物件 (由該事件處理常式所接收) 存取而來的成員:
[C#]
thisXDocument.UI.Alert.(e.Site.text);
[Visual Basic]
thisXDocument.UI.Alert.(e.Site.text)
InfoPathEventHandler 屬性 (如 InfoPathEventHandlerAttribute 類別所定義) 就是要做為事件處理常式函式使用的自訂屬性。
當事件需要 MatchPath 參數時 (如 InfoPathEventHandlerAttribute 類別的 MatchPath 屬性所定義),該參數會指定可識別事件來源的 XPath 運算式。EventType 參數 (如 InfoPathEventHandlerAttribute 類別的 EventType 屬性所定義) 會指定事件的類別。您不應該變更這些參數的值。如果變更這些參數的值,事件處理常式將無法正確編譯,或事件通知將無法依預期發生。
模糊處理事件處理常式中的程式碼
如果您在編譯 Managed 程式碼表單範本時產生的組件上執行模糊處理公用程式 (projectname.dll),InfoPath 將無法在使用者開啟表單時載入該組件。如果您要對事件處理常式的程式碼或其他表單的程式碼進行模糊處理,則必須將要模糊處理的程式碼放在不同的組件,並參照專案中的組件,然後從 FormCode.cs 或 FormCode.vb 中呼叫參照組件的成員。請注意您只能在參照的組件上執行模糊處理公用程式。