Skip to main content
Bring your team and maximize your impact at Dreamforce. Register three or more to unlock $999 passes.

创建和使用自定义控制器

学习目标

完成本单元后,您将能够:

  • 阐述自定义控制器的含义并描述其关键属性。
  • 创建自定义控制器类。
  • 在 Visualforce 页面中使用自定义控制器。

自定义控制器简介

通过在   controller controller 属性中引用控制器类的名称,将自定义控制器添加到 Visualforce 页面。

当页面使用了自定义控制器时,不能再使用标准控制器。页面使用不同的属性来设置自定义控制器。

  1. 要创建新的 Visualforce 页面,请打开 Developer Console,然后单击 File(文件) | New(新建) | Visualforce Page(Visualforce 页面)。输入 ContactsListWithController 作为页面名称。
  2. 在编辑器中,将标记替换为以下内容。
    <apex:page controller="ContactsListWithController">
        <apex:form>
            <apex:pageBlock title="Contacts List" id="contacts_list">
                <!-- Contacts List goes here -->
            </apex:pageBlock>
        </apex:form>
    </apex:page>
    当您尝试保存此页面时,您会收到错误消息,原因是 ContactsListWithController 不存在。不用担心,我们接下来会解决这个问题。

创建自定义控制器 Apex 类

自定义控制器只是一个 Apex 类,您可以使用 Developer Console 自行编写。

有很多系统和实用程序类可以帮助您编写自定义控制器逻辑,但是将类用作自定义控制器的唯一要求是这个类必须存在。

  1. 要创建新的 Apex 类,请打开 Developer Console,然后单击 File(文件) | New(新建) | Apex Class(Apex 类)。输入 ContactsListWithController 作为类名称。

在编辑器中,将代码替换为以下内容。

public class ContactsListWithController {
// Controller code goes here
}

与 Visualforce 页面一样,您需要将更改的内容保存到 Apex。更改的内容并不多,而且还没有做任何事情,但 Visualforce 页面上的错误确实消失了。

  1. 切换到 Visualforce 页面并再次保存。错误提示应该会消失,并且页面已成功保存。
  2. 单击 Preview(预览)可打开页面预览,您可以在进行更改时查看该预览。此时会打开一个新窗口,显示标准 Salesforce 页面标题和侧栏元素,但尚无内容。

乍一看,您创建的这两个新项目似乎不是很有趣。但即便这两个项目 90% 都是占位符代码,Visualforce 页面和 Apex 控制器还是相互链接的。一旦向控制器添加更多代码,您的页面就可以使用控制器。

备注

备注

用中文(简体)学习?在中文(简体)Trailhead Playground 中开始挑战,用括号中提供的译文完成挑战。仅复制并粘贴英文值,因为挑战验证基于英文数据。如果在中文(简体)组织中没有成功通过挑战,我们建议您 (1) 将区域设置切换为美国,(2) 按此处说明将语言切换为英文,(3) 再次单击“检查挑战”按钮。

查看 Trailhead 本地化语言徽章详细了解如何利用 Trailhead 译文。

进阶学习

您可能已经注意到,这个自定义控制器类没有继承另一个类,也不承诺实现符合 Visualforce 控制器要求的接口。即使是复杂的控制器也不会执行这些操作,因为没有任何这样的类可以继承或实现接口。随着对 Apex 的逐步了解,您可以自由地创建自己的类和接口。

添加检索记录的方法

创建运行 SOQL 查询的 getter 方法,返回页面上显示的记录。

大多数控制器的主要目的是检索显示的数据,或处理数据更新。在这个简单的控制器中,您需要做的就是运行一个基础的 SOQL 查询来查找联系人记录,然后将这些记录提供给 Visualforce 页面。

  1. ContactsListWithController 类中,将 // Controller code goes here 注释行替换为以下代码。
    private String sortOrder = 'LastName';
    public List<Contact> getContacts() {
        List<Contact> results = Database.query(
            'SELECT Id, FirstName, LastName, Title, Email ' +
            'FROM Contact ' +
            'ORDER BY ' + sortOrder + ' ASC ' +
            'LIMIT 10'
        );
        return results;
    }
    这段代码添加了私有成员变量、名为 sortOrder 的字符串以及公共方法 getContacts()sortOrder 非常易于理解,它就是用于对联系人进行排序的字段名称。getContacts() 也相当简单,但如果您之前没接触过 Apex,初次阅读时可能不太容易理解。该方法的作用是执行 SOQL 查询以获取联系人记录列表,然后将该联系人列表返回给方法调用者。谁是调用者呢?当然是 Visualforce 页面啦!
    ContactsListWithController 页面中,将 注释行替换为以下标记。
  2. <!-- Contacts List -->
    <apex:pageBlockTable value="{! contacts }" var="ct">
        <apex:column value="{! ct.FirstName }"/>
        <apex:column value="{! ct.LastName }"/>
        <apex:column value="{! ct.Title }"/>
        <apex:column value="{! ct.Email }"/>
    </apex:pageBlockTable>
    When you save this page you should see a familiar looking table of contact information. A contacts list backed by a custom controller

ContactsListWithController 页面的标记看起来应该很熟悉。除了 标签的 controller 属性以外,它与您使用标准控制器创建页面时使用的代码几乎相同。

区别在于评估 {! contacts } 表达式时返回的结果。在该页面上,Visualforce 将表达式转换为对控制器的 getContacts() 方法的调用。该方法返回联系人记录列表,这正符合 的预期。

getContacts() 方法称为 getter 方法,是一种通用模式,其中 Visualforce 标记中的 {! someExpression } 自动连接到控制器中名为 getSomeExpression() 的方法。这是页面访问需要显示的数据的最简单方法。

添加新的操作方法

在自定义控制器中创建操作方法以响应页面上的用户输入。

显示数据固然重要,但对任何网页应用来说,响应用户行为都是必不可少的。借助自定义控制器,您可以通过编写操作方法来响应用户活动,在页面上创建大量的自定义操作。

  1. In the ContactsListWithController class, below the getContacts()method, add the following two methods.
    public void sortByLastName() {
        this.sortOrder = 'LastName';
    }
    public void sortByFirstName() {
        this.sortOrder = 'FirstName';
    }
    These two methods change the value of the sortOrder private variable. sortOrder is used in the SOQL query that retrieves the contacts, and changing sortOrder will change the order of the results.
  2. In the ContactsListWithController page, replace the two <apex:column> tags for ct.FirstName and ct.LastNamewith the following markup.
    <apex:column value="{! ct.FirstName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByFirstName }"
                reRender="contacts_list">First Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>
    <apex:column value="{! ct.LastName }">
        <apex:facet name="header">
            <apex:commandLink action="{! sortByLastName }"
                reRender="contacts_list">Last Name
            </apex:commandLink>
        </apex:facet>
    </apex:column>
    Although the visual appearance remains the same, if you click the First Name and Last Name column headers now, they will change the sort order for the contacts list. Nice!

新标记为每个 组件添加了两个嵌套组件。 本身只有纯文本标题,但我们希望让标题可以点击。 允许我们将列标题的内容设置为任意内容。我们想要的是一个调用正确操作方法的链接。链接是使用 组件创建的,将 action 属性设置为引用控制器中操作方法的表达式。(请注意,与 getter 方法相比,操作方法名称与引用操作方法的表达式相同。)

单击链接会触发控制器中的操作方法。操作方法更改私有变量的排序,然后重新显示表。重新显示表时,会重新评估 {! contacts },通过刚设置的排序重新运行查询。最终结果是按照用户点击请求的顺序重新排列表格。

进阶学习

名字和姓氏列的标题文本在此标记中是硬编码。但是,如果您的用户并非都使用英文怎么办?标准 Salesforce 用户界面具有所有标准对象字段名称的翻译版本,您可以为自定义对象提供自己的译文。如何访问字段名称的翻译版本?如果不是纯文本,试试这个标记:。这是引用字段标签的正确方法,即使您的组织都使用相同的语言,如果更改了字段名称,字段标签也会自动更新。

了解详细信息...

自定义控制器和 Apex 语言让您可以在 Visualforce 页面中执行任何您能想到的事情。

getter 方法将数据从控制器提取到页面。相应的 setter 方法可将值从页面提交回控制器。与 getter 方法一样,setter 方法也使用“set”前缀。此外,这两种都只是带实际参数的方法。

getter 和 setter 的替代方法是使用 Apex 属性。属性是变量与 getter 和 setter 方法的组合,其语法可以更清楚地将它们组合在一起。引用自定义对象的简单属性可以这样声明。

public MyObject__c myVariable { get; set; }

通过省略 get 或者 set,属性可以是公共的或私有的,也可以是只读的,甚至是只写的。除了简单地保存和检索值之外,还可以为 get 或 set 方法创建实现。

属性是 Apex 的通用功能,并非 Visualforce 所特有。Apex 是一种完整的编程语言,它不仅是构建复杂 Visualforce 页面的天然合作伙伴,还用于多种 Lightning 平台开发环境。请参阅此处汇总的 Apex 主题,以及本页面末尾的资源,深度学习 Apex 的多种使用方法。

Visualforce 请求和响应的生命周期起初可能看起来很复杂。特别要注意的是,要清楚 getter 或 setter(使用属性的情况下)的调用没有特定的顺序,因此不能在它们之间引入执行顺序依赖关系。Visualforce 开发人员指南的相关部分提供了更多详细信息,尤其是自定义控制器和控制器扩展章节。

资源

在 Salesforce 帮助中分享 Trailhead 反馈

我们很想听听您使用 Trailhead 的经验——您现在可以随时从 Salesforce 帮助网站访问新的反馈表单。

了解更多 继续分享反馈