首页新闻招聘找找看知识库
  • 读者对象: Force.com 级开发者

     

     

         使用VisualForce的Force.com开者都会感叹其页件在交互界面复用简单灵活性,但是也会碰到一个棘手的问题

    当Visualforce面在引用一个,如何取到对应的控制类的数据呢? 因为页面和件所属的控制类之没有

    直接的系。搜索了一下developforce board, 发现一篇介绍这方面技的妙文,原文出处 

    http://wiki.developerforce.com/index.php/Controller_Component_Communication 基于自己的理解现转译如下,

    希望和大家一起分享些极具造力的实现。 现对翻译术语做一下界定:

               View 层元素:

                            页面(Page),页面组件(Component),

               Controller 层元素: 

                            页面控制类(PageController), 组件控制类 (ComponentController) 

     

        第一步, 我需要建一个Visualforce面控制类的基本抽象类 PageControllerBase, 个基类会保留一个对组件控制类的属性,同暴露自身引用

    公用以便页面组件对行引用,看到里不禁想起了面向设计里面的friendly关字,是不是很眼熟呢? 明显这封装的破坏,但是它是友好而具有

    性意的破坏  :) 艺术性的代往往人看不懂,但请继续往下看

     

    public with sharing virtual class PageControllerBase { 

       private ComponentControllerBase myComponentController;

       public virtual ComponentControllerBase getMyComponentController() {

          return myComponentController;

       }

       public virtual void setComponentController(ComponentControllerBase compController) {

          myComponentController = compController;

       }

       public PageControllerBase getThis() {

          return this;

       }

    }

     

        第二步,我需要建一个Visualforce 件控制类的基本抽象类 ComponentControllerBase, 个基类同会保留一个对页面控制类的属性.

    由于它会作为页面控制类的象存在与面控制类中,不是将自身引用暴露为共有方法,而是直接将自身引用植入其面控制类属性中,这样

    如果页面控制类作为页面组件的输入参数,那么输入的页面控制类就可以直接访问组件控制类所有的属性和公用方法。类与类之间的互相渗透抽象目标基本达成!

     

    public with sharing virtual class ComponentControllerBase {

     public PageControllerBase pageController { get; 

     set {

    if (value != null) {

    pageController = value;

    pageController.setComponentController(this);

    }

    }

    }

    }

     

        第三步, 创建具体组件控制类及其页面组件,这个步骤相对简单,跟一般的页面组件使用基本类似,只是它继承了父类特有的"潜伏"气质 :)

    在页面组件中我们可以看到有页面控制类会被作为参数传入,这是重要一环,使这个页面组件可以植入到任意一个继承了我们第一步创建的抽象页面控制类

    的页面控制类中。 

     

    public with sharing class MyComponentController extends ComponentControllerBase {

    private Integer myValue = 3;

    public Integer getIntValue() {

    return myValue; 

    }

    public void incrementValue() {

    myValue++;

    }

    }

     

    <apex:component controller="MyComponentController" >

      <apex:attribute name="pageController" 

          type="PageControllerBase" 

          assignTo="{!pageController}" 

          required="true" 

          description="The controller for the page." />

     

      <apex:outputPanel layout="block" style="font-size: 12pt; border: 1pt solid black; width: 250px;">

        <center>

          <apex:outputText value="This is in the component." />

          <br/>

          <apex:outputText value="initial int value: {!intValue}" />

        </center>

      </apex:outputPanel>

    </apex:component>

     

     

        第四步,建具体页面控制类及页面, 在具体类的实现中,我们需要重写抽象类的函数,赋予页面控制类具体的组件控制类引用。

    在页面的实现中,会将页面控制类作为参数传入到页面组件中。所有组件控制类进行的操作和数据对页面控制类可见,从而时页面对

    组件控制类的数据可见并回显到页面。

     

    public with sharing class MyPageController extends PageControllerBase {

    public MyComponentController myComponentController { get; set; }

    public override void setComponentController(ComponentControllerBase compController) {

    myComponentController = (MyComponentController)compController;

    }

      public override ComponentControllerBase getMyComponentController() {

        return myComponentController;

      }

     

      public PageReference callComponentControllerMethod() {

        myComponentController.incrementValue(); 

        return null;

      } 

    }

     

    <apex:page controller="MyPageController" showHeader="false">

      <center>

        <apex:outputPanel layout="block" style="font-size: 16pt; margin-top: 50px; width: 400px">

          <h2>Sample Illustrating How to Establish Communication Between Page and Component</h2>

        </apex:outputPanel> 

        <apex:outputPanel layout="block" style="width: 300px;">

          <hr/>

          <h1>Component Shown below:</h1><hr/>

          <c:MyComponent pageController="{!this}" />

          <hr/>

          <br/><br/>

          <apex:form >

            <apex:commandButton style="font-size: 12pt; color: black" 

                 action="{!callComponentControllerMethod}" 

                 value="Call Component Controller Method" 

                 rerender="output" />

            <br/>

            <apex:outputText value="Clicking the button above will call the 

                     method on the component controller to increment the initial

                     value from the component above." />

          </apex:form>

          <apex:outputPanel id="output" style="font-size: 12pt;"> 

            <center> 

      <apex:outputText value="{!myComponentController.intValue}" />

      <hr/>

    </center>

          </apex:outputPanel>

        </apex:outputPanel>

      </center>

    </apex:page>

     

        最后,原文还对一个页面如何引用多个页面组件做了扩展介绍,这里不再赘述,详情请见英文原文。

登录后才能评论,请先登录注册