HtmlDataTable组件属于UIData家族的HTML数据列表实现,组件中提供了rowStyleClass等方法来控制行的显示,,如果你在rowStyleClass中加入两个样式类,并使用逗号分开,那么渲染的每一行会交替使用这两个样式类进行显示,同理多个样式类也会循环交替显示。但是如果我想根据业务的情况具体指定某行显示成特定的样式,HtmlDataTable就 无能为力了,然而这种业务又很常见,比如我想高亮显示列表中时间过期的行等等......
    下面是一个例子,显示了我的藏书列表,我想让计算机类书籍的行使用红色背景,文学类书籍的行使用白色背景,经济学类书籍的行使用蓝色列表。
     1.首先是Book模型
        
package net.blogjava.fangshun.book;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.model.SelectItem;


/** *//**
 * 书籍模型
 * @author shun.fang
 *
 */

public class Book implements Serializable 
{
    private int id;    //书籍编号
    private String name; //书籍名称
    private int type; //书籍类型
    

    public Book() 
{
        
    }
    

    /** *//**
     * type
     * @param id
     * @param name
     * @param type
     */

    public Book(int id, String name, int type) 
{
        // TODO Auto-generated constructor stub
        this.id = id;
        this.name = name;
        this.type = type;
    }
    

    public int getId() 
{
        return id;
    }

    public void setId(int id) 
{
        this.id = id;
    }

    public String getName() 
{
        return name;
    }

    public void setName(String name) 
{
        this.name = name;
    }

    public int getType() 
{
        return type;
    }

    public void setType(int type) 
{
        this.type = type;
    }
    
    public static final int COMPUTER_BOOK = 1;    //计算机类
    
    public static final int ART_BOOK = 2;        //文学类
    
    public static final int ECONOMY_BOOK = 3;     //经济类
    
    
    private List<SelectItem> items;
    

    /** *//**
     * 为下拉菜单提供模拟数据
     * @return
     */

    public List<SelectItem> getItems() 
{

        if(items == null) 
{
            items = new ArrayList<SelectItem>();
            
            SelectItem item = new SelectItem();
            item.setLabel("计算机类");
            item.setValue(COMPUTER_BOOK);
            items.add(item);
            
            item = new SelectItem();
            item.setLabel("文学类");
            item.setValue(ART_BOOK);
            items.add(item);
            
            item = new SelectItem();
            item.setLabel("经济学类");
            item.setValue(ECONOMY_BOOK);
            items.add(item);
        }
        return items;
    }
}

 
  
     2. book的列表模型
package net.blogjava.fangshun.book;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIData;
import javax.faces.model.ListDataModel;


/** *//**
 * 书籍列表模型
 * @author shun.fang
 *
 */

public class BookList implements Serializable 
{
    //    绑定使用此BookList作为数据源的UIData组件,常使用的是HtmlDataTable这个实现组件
    //  这样可以通过调用BookList模型来间接访问到HtmlDataTable组件,以便控制组件
    //    内部的状态
    private UIData uiData;    
    
    private ListDataModel books;

    //UIData组件的values属性可以直接读取DataModel家族的对象
    //这里没有返回Collection集合对象,是为了在自定义的BookListDataModel
    //对象中控制UIData组件的状态

    public ListDataModel getBooks() 
{

        if(books == null) 
{
            
            books = new BookListDataModel(createBooks());
        }
        return books;
    }


    public void setBooks(ListDataModel books) 
{
        this.books = books;
    }


    public UIData getUiData() 
{
        return uiData;
    }


    public void setUiData(UIData uiData) 
{
        this.uiData = uiData;
    }
    

    /** *//**
     * 创建模拟数据
     * @return    List<Book>
     */

    public List<Book> createBooks() 
{
        //使用HashMap是为了打乱数据的排序
        Map<Integer, Book> bs = new HashMap<Integer, Book>();
        

        for(int i = 0; i < 50; i++) 
{
            bs.put(i, new Book(i, "book_" + i, (i%3+1)));
        }
        
        List<Book> lst = new ArrayList<Book>();
        lst.addAll(bs.values());
        return lst;
    }
}

 
 
 3. 自定义的数据模型
package net.blogjava.fangshun.book;

import java.util.List;

import javax.faces.context.FacesContext;
import javax.faces.el.VariableResolver;
import javax.faces.model.ListDataModel;

import org.apache.myfaces.component.html.ext.HtmlDataTable;


/** *//**
 * 集成了ListDataModel为Book模型提供自定义样式的支持
 * @author shun.fang
 *
 */

public class BookListDataModel extends ListDataModel 
{
    

    public BookListDataModel(List<Book> books) 
{
        super(books);
    }
    

    /** *//**
     * 覆写了DataModel对象的getRowData方法,每次uiData组件从模型列表获取新一行记录
     * 的时候,是从这里发起的,所以在这里可以通过获取uiData组件,来对uiData组件的状态进行
     * 调整。目前的调整就是根据业务的需要对uiData组件的每一行样式进行特殊指定。
     */
    @Override

    public Object getRowData() 
{
        // TODO Auto-generated method stub
        
        /////////////////////////////////////////////////////////////
        //通过变量解析获取request scope中的BookList列表模型
        FacesContext facesContext = FacesContext.getCurrentInstance();
        VariableResolver vr = facesContext.getApplication().getVariableResolver();
        BookList bookList = (BookList)vr.resolveVariable(facesContext, "booking");    
        /////////////////////////////////////////////////////////////
        
        //间接得到绑定BookList列表模型的uiData组件,并向下转型成HtmlDataTable(myfaces扩展类型)组件
        HtmlDataTable table = (HtmlDataTable)bookList.getUiData();
        
        //获取当前行的Book实例
        Book book = (Book)super.getRowData();
        
        //根据当前行Book实例的业务特征为HtmlDataTable组件设置渲染行样式
        setCurrentRowStyle(table, book.getType());
        
        return book;
    }
    

    /** *//**
     * 根据不同的类型,设置当前行的样式
     * @param table
     * @param type
     */

    private void setCurrentRowStyle(HtmlDataTable table, int type) 
{

        switch (type) 
{
            case Book.COMPUTER_BOOK:
                //System.out.println("computers");
                table.setRowStyleClass("computers");    //设置计算机书籍样式
                break;
            case Book.ART_BOOK:
                //System.out.println("arts");
                table.setRowStyleClass("arts");        //设置文学书籍样式
                break;
            case Book.ECONOMY_BOOK:
                //System.out.println("C");
                table.setRowStyleClass("economy");        //设置经济书籍样式
                break;
            default:
                break;
        }
    }
}

 
 
4.页面
<?xml version="1.0" encoding="UTF-8"?>
<jsp:root
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:jsp="http://java.sun.com/JSP/Page"
    xmlns:t="http://myfaces.apache.org/tomahawk"
    version="2.0">
  <jsp:directive.page session="false"
                      contentType="text/html;charset=UTF-8"
                      pageEncoding="UTF-8"/>
  <jsp:output doctype-public="-//W3C//DTD XHTML 1.1//EN"
              doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
              doctype-root-element="html" omit-xml-declaration="true"/>
  <f:view>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <meta content="text/html;charset=UTF-8" http-equiv="Content-Type"/>
      <title>特定样式</title>
      <style>
              .computers  {
                  background-color: red;
              }
            .arts {
                  background-color: white;
              }
              
              .economy {
                  background-color: blue;
              }
              
      </style>
    </head>
    <body>
      <h:form>
        <t:dataTable id="book"
                       var="bk"
                       rowStyleClass="computers" 
                       binding="#{booking.uiData}"
                       value="#{booking.books}">
          <t:column>
            <f:facet name="header">
              <h:outputText value="编号"/>
            </f:facet>
            <h:outputText value="#{bk.id}"></h:outputText>          
          </t:column>
          
          <t:column>
            <f:facet name="header">
              <h:outputText value="书名"/>
            </f:facet>
            <h:outputText value="#{bk.name}"></h:outputText>          
          </t:column>
          <t:column>
            <f:facet name="header">
              <h:outputText value="类别"/>
            </f:facet>
            <t:selectOneMenu value="#{bk.type}" displayValueOnly="true" >
                <f:selectItems value="#{book.items}"/>
            </t:selectOneMenu>            
          </t:column>
        </t:dataTable>
    </h:form>
    </body>
    </html>
  </f:view>
</jsp:root> 
5.简要配置
 
  <managed-bean>
    <managed-bean-name>book</managed-bean-name>
    <managed-bean-class>net.blogjava.fangshun.book.Book</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>
  
   <managed-bean>
    <managed-bean-name>booking</managed-bean-name>
    <managed-bean-class>net.blogjava.fangshun.book.BookList</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>  
6.显示效果
总结:主要是靠自定义的DataModel对象,在获取每一行记录的开始,来根据业务为绑定的uiData组件设置自己的样式,这样就可以自由灵活的控制数据列表每一行记录产生时的状态。上面的代码在jdk1.5下需要myfaces支持,完全测试通过,希望可以为大家在使用jsf上得到更多的提示和技巧!
                                                                                                                              方顺 
fangshun1980@hotmail.com