Visualforce框架是遵循MVC結構的。Visualforce頁面代表了“視圖”部分,Salesforce的各種對象代表了“模型”部分,而Apex則代表了“控制器”部分。
Visualforce頁面綁定控制器
在Visualforce頁面中的“apex:page”標簽里可以綁定控制器。
控制器是一個Apex類,可以是標准的控制器類,也可以是用戶自己開發的Apex類。
標准控制器類
Salesforce中為標准對象預定義了標准的控制器類,不需要用戶配置即可直接使用。
比如要在Visualforce頁面中綁定Account對象,可以這樣寫:
<apex:page standardController="Account">
輸入URL參數
每一個Visualforce頁面都可以通過一個預定義的URL來進入。在基本的Salesforce根地址后面加入“/apex/頁面名”即可進入Visualforce頁面。在URL的最后還可以加入“?id=”參數來傳入頁面中要顯示的對象的ID。
示例:建立Visualforce頁面並顯示Account對象的內容
在系統中,有一個Account對象,其ID是“0010Y00000H3TiV”。
- 在Developer Console中,建立Visualforce頁面,命名為“CustomAccountView”。
- 在Visualforce頁面的編輯區域輸入以下代碼:
<apex:page standardController="Account">
<apex:pageBlock title="Account Info">
<apex:pageBlockSection>
Name: {! Account.Name }
<br/>
Phone: {! Account.Phone }
<br/>
Owner: {! Account.Owner.FirstName & ' ' & Account.Owner.LastName }
</apex:pageBlockSection>
</apex:pageBlock>
</apex:page>
- 將瀏覽器中的Salesforce主界面下的URL地址修改一下,保留根地址,在后面加入“/apex/CustomAccountView?id=0010Y00000H3TiV”
- 頁面將顯示傳入的Account對象的信息。
代碼解釋
- 在代碼的“apex:page”標簽中,使用了“standardController”屬性,將其定義為“Account”。這就是告訴Salesforce該頁面在載入時,需要在URL中接收一個Account對象的ID值,並在數據庫中查詢得到該對象的信息,存入“Account”變量供頁面使用。
- 在代碼中,使用“{! Account.XXX }”來調用得到的Account對象的字段值。當Account對象有相關聯的對象時,也可以顯示相關聯對象的字段值,比如“Owner”就是和Account對象相關聯的一個User對象,用“ {! Account.Owner.FirstName }”即可調用“Owner”的“FirstName”字段值。
使用標准組件顯示對象內容
在示例代碼中,Account對象的內容是通過“{! Account.XXX }”來手動顯示的。
Visualforce中提供了一系列標准組件,可以直接格式化輸出對象的各種內容。
比如將以上代碼修改為:
<apex:page standardController="Account">
<apex:pageBlock title="Account Info">
<apex:pageBlockSection>
<apex:detail />
</apex:pageBlockSection>
</apex:pageBlock>
</apex:page>
當該頁面顯示Account對象時,其外觀和Salesforce標准的Account詳細信息頁面一樣,包括了各個字段的值和相關列表。
代碼中的“apex:detail”就是預定義的顯示詳細信息的組件。
在控制器中綁定列表變量
使用標准控制器類,不光可以綁定一個對象變量,也可以綁定一個列表變量。
在“apex:page”標簽中,設置“recordSetVar”屬性,即可讓標准控制器返回一個包含此對象數據的列表。
比如:
<apex:page standardController="Account" recordSetVar="accounts">
<apex:pageBlock title="Account Info">
<apex:pageBlockTable value="{! accounts }" var="acc">
<apex:column value="{! acc.Name }"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:page>
在上面的代碼中,使用了“recordSetVar="accounts"”來接收標准控制器返回的包含Account對象的列表。一般情況下,列表變量的名字是對象名字的復數形式。
在頁面內容中,使用“apex:pageBlockTable”組件來循環顯示對象列表中的每個元素的內容。“value”屬性可以決定在組件里循環顯示哪個對象列表,代碼中是“accounts”列表變量。“var”屬性可以決定在每個循環中,代表單個對象變量的名稱,代碼中是“acc”,所以在循環中,用“{! acc.Name }”來顯示每個對象變量的Name字段值。
控制器擴展
在標准的控制器類中,開發者可以很方便的使用系統自定義的各種功能。而控制器擴展則可以對標准控制器類的功能進行擴展。
在“apex:page”標簽中,在已經有“standardController”變量后,設置“extensions”變量,即可設定擴展類。
一個擴展類的構造函數必須使用ApexPages.StandardController類型的參數。
代碼示例:
public class ExampleControllerExtension {
private final Account acc;
public ExampleControllerExtension(ApexPages.StandardController stdController) {
// 使用標准控制器變量的getRecord()方法來得到相應SObject對象的值
this.acc = (Account)stdController.getRecord();
}
public void getExampleCustomMessage() {
return 'Hello world!';
}
// 其他自定義方法
...
}
<apex:page standardController="Account" extensions="ExampleControllerExtension">
{!exampleCustomMessage}
</apex:page>
在上面的代碼中,建立的Visualforce頁面會顯示“Hello world!”字樣,就是從控制器擴展的自定義方法中實現的。
在標准控制器擴展中載入特定字段
標准控制器默認使用SOQL載入對象的一些字段。如果需要讓其載入更多的字段,在擴展標准控制器的時候,可以使用addFields()方法來聲明。
比如以下代碼:
public class ExampleControllerExtension {
private final Account acc;
public ExampleControllerExtension(ApexPages.StandardController stdController) {
// 使用addFields()方法讓控制器載入更多的字段
controller.addFields(new List<String>{'ExampleField1__c', 'ExampleField2__c'});
this.acc = (Account)stdController.getRecord();
}
...
}
<apex:page standardController="Account" extensions="ExampleControllerExtension">
<!-- 在此處可以使用控制器擴展中聲明的ExampleField1__c、ExampleField2__c字段了 -->
</apex:page>
自定義控制器類
除了標准控制器類,Visualforce頁面還可以指定自定義的Apex類作為控制器類。
此時在“apex:page”標簽中就不需要使用“standardController”屬性,而是設定“controller”屬性的值為自定義的Apex類的名字。
Salesforce有默認的“get函數”機制,可以從控制器類中自動得到頁面中使用的變量的值。當頁面中使用變量“abc”,那么“abc”的值會自動由控制器中的“getAbc()”函數來得到。此機制適用於單獨對象變量和列表對象變量。
示例代碼:自定義控制器類並在Visualforce頁面中顯示一組Account對象
首先,建立一個自定義的Apex類,名字叫“CustomAccountListController”。代碼如下:
public class CustomAccountListController {
public List<Account> getAccounts() {
List<Account> results = Database.query(
'SELECT Id, Name, Phone, Fax ' +
'FROM Account ' +
'LIMIT 10'
);
return results;
}
}
然后建立一個Visualforce頁面,名字叫“CustomAccountListView”,代碼如下:
<apex:page controller="CustomAccountListController">
<apex:pageBlock title="Account Info">
<apex:pageBlockTable value="{! accounts }" var="acc">
<apex:column value="{! acc.Id }"/>
<apex:column value="{! acc.Name }"/>
<apex:column value="{! acc.Phone }"/>
<apex:column value="{! acc.Fax }"/>
</apex:pageBlockTable>
</apex:pageBlock>
</apex:page>
預覽此頁面,可以看到系統中的10個Account對象的信息已經顯示在了頁面中。
代碼解釋
- 當建立了Apex類之后,在Visualforce頁面的“apex:page”標簽中,將“controller”屬性的值設置為Apex類的名字,即可建立頁面和類的關系。此時Apex類便成為了頁面的控制器。
- 在頁面中,未經定義,直接使用了列表變量“accouonts”進行循環顯示。此時,Salesforce會自動在控制器類中尋找名為“getAccounts()”的函數來得到列表變量的值。如果將上面的頁面代碼中的“accounts”變為“fakeObjects”,將Apex類中的“getAccounts()”函數改名為“getFakeObjects()”,也可以得到同樣正確的結果。