TDataGrid使用教程From PRADO Wiki
TDataGrid使用教程
Qiang Xue (qiang.xue@gmail.com)
Copyright 2005. All Rights Reserved.
翻译:Sail Lee (sail_lee@21cn.com)
翻译说明:原文见PRADO的wiki,由于译者水平有限,部分翻译难免有错漏之处,权当抛砖引玉,望各位补充、斧正。
目录
1 概览
2 第一部分:TDataGrid的使用实例
2.1 实例1:使用自动生成的列
2.2 实例2:手动指定列
2.3 实例3:与数据网格交互
2.4 实例4: Paging and sorting
3 第二部分:Enhancing TDataGrid
3.1 实例5: Using custom paging
3.2 实例6: Writing new column classes
概览 Datagrid在建立复杂的Web应用程序中是一个重要的组件。它以网格的形式显示数据。用户能根据一些列进行数据排序,通过不同数据的页面进行导控,并执行诸如数据行的编辑、删除等操作。最近加入的TDataGrid控件实现了一个数据网格,它在标准PRADO控件库中是最复杂和最强大的控件之一。但是,使用TDataGrid不象写它那么难。事实上,能轻易地使用是这个控件的目的。在本教程中,我希望能向你展示怎样使用TDataGrid。
一个数据网格是一个由列和项(也叫行)组成的二维表。一行由一个个单元格组成。当各条目被数据绑定并注入单元格来表述内容是,列支配着单元格如何依照它们的列之间的联系被显示出来。
要使用TDataGrid:
我们首先在模板或代码中定义它的列。在PRADO中列是按照控件的形式实现的,因而是可配置的。 然后,我们设定数据网格的DataSource(数据源)属性。一个数据源必须是一个数组或一个Traversable接口的对象实现(在PHP5的SPL扩展中定义)。一个典型的应用数据源是一个选定的SQL数据库查询子集的运行结果。 上述步骤完成后,调用数据网格的dataBind()方法用实际的数据来实例化网格中的条目和单元格。 在PRADO释出的版本中包含了五种类型的列:
TBoundColumn是用数据的特定字段和在单元格中显示那个字段的数据组合成的。 THyperLinkColumn在单元格中显示一个标题和URL能被静态指定或绑定到运行数据字段的超链结。 TEditCommandColumn在单元格中,依照所在单元格条目的状态显示编辑/更新/取消等命令按钮。 TButtonColumn在单元格中显示一个命令按钮。 TTemplateColumn依照它不同的模板定义显示单元格。 这个教程包括两个部分。第一部分,我们用一些例子来是否TDataGrid的用法。在第二部分,我们描述一下怎样用你自己的column类来增强TDataGrid的功能。
第一部分:TDataGrid的使用实例 在我们展示实例前,先来说明一下将在我们所有实例中用到的数据。为方便起见,我们将使用以下示范数据:
$data=array(
array('id'=>'ITN001','name'=>'Motherboard','price'=>100.00,'imported'=>true),
array('id'=>'ITN002','name'=>'CPU','price'=>150.00,'imported'=>true),
array('id'=>'ITN003','name'=>'Harddrive','price'=>80.00,'imported'=>true),
array('id'=>'ITN004','name'=>'Sound card','price'=>40.00,'imported'=>false),
array('id'=>'ITN005','name'=>'Video card','price'=>150.00,'imported'=>true),
array('id'=>'ITN006','name'=>'Keyboard','price'=>20.00,'imported'=>false),
array('id'=>'ITN007','name'=>'Monitor','price'=>300.00,'imported'=>true),
array('id'=>'ITN008','name'=>'CDRW drive','price'=>40.00,'imported'=>true),
array('id'=>'ITN009','name'=>'Cooling fan','price'=>10.00,'imported'=>false),
array('id'=>'ITN010','name'=>'Video camera','price'=>30.00,'imported'=>true)
);
假如你想使用来自一些数据库查询结果的数据,你可以引用下面的语句:
$data=$adodb->Execute($sqlSelection);
$adodb指向一个AdoDB函数库的DB连接。
下面,我们假设我们在一个命为HomePage的页面中使用TDataGrid。
实例1:使用自动生成的列 TDataGrid默认会建立一个基于绑定数据的结构的列的列表。每个列都是TBoundColumn类型。一般来说,TDataGrid会读出数据的首行,导入行中的字段名,并构造出每个字段的列。对于我们的示范数据,有四个列被生成,每个列分别和id、name、price和imported字段联结在一起。
下列实例文件中的命名约定是ExampleX.php和ExampleX.tpl,X指实例的编号。
我们第一个实例包含了下面两个文件:
Example1.tpl
...
<com:TDataGrid ID="datagrid"
CellPadding="3"
CellSpacing="0"
HeaderStyle="background-color:#BFCFFF;"
ItemStyle="background-color:#F0F0F0;"
AlternatingItemStyle="background-color:#FFFFFF;" />
...
Example1.php
<?php
class Example1 extends TPage
{
public function onInit($sender,$param)
{
// .... data initialization here
if(!$this->IsPostBack)
{
$this->datagrid->setDataSource($data);
$this->datagrid->dataBind();
}
}
}
?>
下图展示数据网格的显示结果。
注意上面的图,在初始化非postback的页面请求时,对于数据网格我们仅仅调用了databind()一次。这是因为 TDataGrid使用viewstate来记住网格里有哪些数据。在postback到同一个页面期间,它将尝试从viewstate中恢复这些数据。
就象我们从这个例子中看到的一样,它自动地生成列来显示格式化的数据,非常容易使用。被生成的是TBoundColumn类型的列,已经被绑定到一个数据源字段去,而且单元格已经用那些要在列里显示的相应字段的数据初始化过了。
这里,我们不会解释如何在模板中配置数据网格的属性,它们主要和网格展现风格有关。每个属性更详细的说明可在TDataGrid里面中找到。
实例2:手动指定列 实例1给我们的数据一个很好的展现。但是,在实践中我们会因为以下原因而感到不足:
我们想文本的首字母大写。 我们想已超链接来代替产品ID列的静态文本。每个超链接都指向一个具体说明更多关于该产品详细信息的Web页面。 我们想把价格排列在每个单元格的右边而且还带上美元符号的前缀。 我们想用校验框来表示产品是否进口,而不想用真假值来显示。 要完成以上这些目标,我们必须要手动指定列,这比依靠自动生成更好。下面我们演示我们页面模板的第二个实例。页面代码和第一个实例相同。
Example2.tpl
...
<com:TDataGrid ID="datagrid"
AutoGenerateColumns="false"
CellPadding="3"
CellSpacing="0"
HeaderStyle="background-color:#BFCFFF;"
ItemStyle="background-color:#F0F0F0;"
AlternatingItemStyle="background-color:#FFFFFF;">
<com:THyperLinkColumn DataTextField="id" HeaderText="ID"
NavigateUrl="http://www.xisc.com/" Target="_blank"/>
<com:TBoundColumn DataField="name" HeaderText="Name" />
<com:TBoundColumn DataField="price" HeaderText="Price"
DataFormatString="$%.2f" ItemStyle="text-align:right;"/>
<com:TTemplateColumn HeaderText="Imported" ItemStyle="text-align:center">
<prop:ItemTemplate>
<com:TCheckBox
Checked="#$this->Container->Container->Data['imported']"
Enabled="false" />
</prop:ItemTemplate>
</com:TTemplateColumn>
</com:TDataGrid>
...
当上面的模板显示时,我们将AutoGenerateColumn属性设置为false来阻止列的自动生成。假如它为true的话,自动生成的列将附加在手动生成的列上。
在TDataGrid的tag内,我们加入一些包括TBoundColumn、THyperLinkColumn和TTemplateColumn在内的列的定义。
对于id这个列,我们用THyperLinkColumn。我们设定它的DataTextField为id,意思就是数据源中id字段的值,将会做为超链接显示的标题,被用于列中。 对于name这个列,我们用TBoundColumn,它的DataField属性设成name,在数据源中指向name字段。TBoundColumn会显示name字段中相应的值。我们也要设定HeaderText属性为name。 对于price列,我们用TBoundColumn并将DataField设成price。我们还要设定DataFormatString和ItemStyle属性,这样价格就会以美元符号为前缀显示在右边。 最后,对于imported列,我们用TTemplateColumn。我们在它的ItemTemplate属性中定义一个校验框,以便可以校验imported数据值是否为true。 下图是我们的显示结果:
实例3:与数据网格交互 在这个实例中,我们将允许用户以行的方式来改动我们的数据行。我们将加入一个TEditCommandColumn到我们的数据网格中来。它显示一个列的编辑按钮。假如它们中的一个被点击,一个数据网格的OnEditCommand事件将被唤起。通过在事件处理程序中把相应数据网格项设定成编辑模式,我们可以允许用户来改动包含在该项中的数据。数据网格也将自动显示一个更新按钮和一个取消按钮来重置或放弃修改。更新或取消操作分别由数据网格的 OnUpdateCommand或OnCancelCommand事件的事件处理程序来处理。
本实例的网页模板见下面:
...
<com:TDataGrid ID="datagrid"
AutoGenerateColumns="false"
CellPadding="3"
CellSpacing="0"
HeaderStyle="background-color:#BFCFFF;"
ItemStyle="background-color:#F0F0F0;"
AlternatingItemStyle="background-color:#FFFFFF;"
OnEditCommand="editItem"
OnUpdateCommand="updateItem"
OnCancelCommand="cancelItem">
<com:THyperLinkColumn DataTextField="id" HeaderText="ID"
NavigateUrl="http://www.xisc.com/" Target="_blank"/>
<com:TBoundColumn DataField="name" HeaderText="Name" />
<com:TBoundColumn DataField="price" HeaderText="Price"
DataFormatString="$%.2f" ItemStyle="text-align:right;"/>
<com:TTemplateColumn HeaderText="Imported" ItemStyle="text-align:center">
<prop:ItemTemplate>
<com:TCheckBox
Checked="#$this->Container->Container->Data['imported']"
Enabled="false" />
</prop:ItemTemplate>
<prop:EditItemTemplate>
<com:TCheckBox ID="importCheck"
Checked="#$this->Container->Container->Data['imported']"
Enabled="true" />
<
/prop:EditItemTemplate>
</com:TTemplateColumn>
<com:TEditCommandColumn ButtonType="LinkButton"
ItemStyle="text-align:center" HeaderText="Action"
EditText="Edit" UpdateText="Update" CancelText="Cancel" />
</com:TDataGrid>
...
在上面的模板中,我们作了几项改变。我们定义了TTemplateColumn的EditItemTemplate。它常常在编辑模式下用于生成单元格。我们也会加入TEditCommandColumn来显示编辑、更新或取消按钮。最后,我们附上事件处理程序到下面的数据网格事件中:
OnEditCommand:当一个编辑按钮被点击时唤起。在附带的事件处理程序中(见下面的展示),我们把相应的数据网格项设定成编辑模式。注意,事件参数包含了指向引起编辑事件的数据网格项对象的项目字段。
public function editItem($sender,$param)
{
$this->datagrid->setEditItemIndex($param->item->ItemIndex);
$this->datagrid->dataBind();
}
OnUpdateCommand:当一个更新按钮被点击时唤起。在附带的事件处理程序中(见下面的展示),我们重新得到的输入数据并用它们来更新现有的数据。注意,在我们从事件参数中得到引起事件的数据网格项之后,我们用它的Cells属性来找出包含输入控制的单元格(例如:$param->item->Cells[1]->Bodies[0]->Text)。
public function updateItem($sender,$param)
{
$dataSource=$this->datagrid->getDataSource();
$product=$dataSource[$param->item->ItemIndex];
$product['name']=$param->item->Cells[1]->Bodies[0]->Text;
$product['price']=floatval($param->item->Cells[2]->Bodies[0]->Text);
$product['imported']=$param->item->Cells[3]->importCheck->Checked;
$dataSource[$param->item->ItemIndex]=$product;
$this->datagrid->setSelectedItemIndex($param->item->ItemIndex);
$this->datagrid->setDataSource($dataSource);
$this->datagrid->dataBind();
}
OnCancelCommand:当一个取消按钮被点击时唤起。在附带的事件处理程序中(见下面的展示),我们清除掉数据网格的编辑模式。
public function cancelItem($sender,$param)
{
$this->datagrid->setEditItemIndex(-1);
$this->datagrid->dataBind();
}
注意,在上面的程序中,我们通常在事件处理程序的末尾调用dataBind()。这是让数据网格在我们操作后重建它的内容。
下面的图表分别展示了我们浏览模式和编辑模式下的数据网格:
实例4: Paging and sorting 第二部分:Enhancing TDataGrid 实例5: Using custom paging 实例6: Writing new column classes