English Version: http://dflying.dflying.net/1/archive/114_display_one_item_in_a_collection_using_aspnet_atlas_itemview_control.html
在这个系列中,我将介绍一些Atlas Sys.UI.Data中较高级的控件,包括:
- Sys.UI.Data.ListView:使用ASP.NET Atlas ListView控件显示列表数据
- Sys.UI.Data.ItemView:使用ASP.NET Atlas ItemView控件显示集合中的单个数据
- Sys.UI.Data.DataNavigator:使用 ASP.NET Atlas PageNavigator控件实现客户端分页导航
- Sys.UI.Data.SortBehavior:使用ASP.NET Atlas SortBehavior实现客户端排序
- Sys.UI.Data.XSLTView:使用ASP.NET Atlas XSLTView控件用XSLT修饰并显示XML数据
这篇是其中的第二篇:
使用ASP.NET Atlas ItemView控件显示集合中的单个数据
有时候我们需要显示给用户列表中某一项的详细信息,例如,在购物程序中的产品详细情况。ASP.NET Atlas ItemView客户端控件为您提供了对这项功能的支持,就像ASP.NET服务器端控件DetailsView一样,但Atlas ItemView控件完全在客户端运行。
ItemView类(ListView类同样,见使用ASP.NET Atlas ListView控件显示列表数据 )继承于Sys.UI.Data.DataControl基类。该基类提供了一些公共的属性,包括:
- canMoveNext:当前记录后是否有下一条记录。
- canMovePrevious:当前记录前是否有前一条记录。
- data:控件包含的数据集合。
- dataIndex:当前记录的index。
- dataItem:基于dataIndex的当前的记录。
- length:记录的条目数。
同时还包括下列方法:
- addItem:添加一条记录到当前的数据集合中。
- deleteCurrentItem:删除基于dataIndex的当前记录。
- moveNext:如果canMoveNext为true,将dataIndex加1,指向下一条记录。
- movePrevious:如果canMovePrevious为true,将dataIndex减1,指向前一条记录。
请注意所有的以上操作都仅在客户端,也就是说只修改了客户端的数据。所以如果您希望将改变提交到服务器,则需要调用
DataSource
的相应方法。
ItemView通过继承获得了以上的属性和方法,并且还对基类有如下扩展:
- itemTemplate:指定项目模版。Atlas可以根据这个模版渲染您的内容。
- emptyTemplate:指定无数据时的模版。当数据集合为空或者DataSource还在取得数据的过程中时,Atlas会显示这个模版。
以上是ItemView的简要介绍。让我们通过一个例子来熟悉ItemView。这个程序基于Atlas官方发布的示例程序,并适当做了一些简化。
首先暴露一个Web Service以被Atlas使用。
定义item entry类:
class Entry
public class Entry
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
{
private string _name;
private string _description;
private int _id;
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectField(true, true)]
public int Id
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _id; }
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _id = value; }
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectField(false)]
[DefaultValue("New row")]
public string Name
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _name; }
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _name = value; }
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectField(false)]
[DefaultValue("")]
public string Description
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return _description; }
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ _description = value; }
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public Entry()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_id = -1;
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
public Entry(int id, string name, string description)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_id = id;
_name = name;
_description = description;
}
}
定义
Web Methods
。我们需要提供
Select
,
Insert
,
Update
以及
Delete
方法以期对我们的数据集合进行完整的
CRUD
操作。注意到我们在初始化数据时使用了
System.Threading.Thread.Sleep(2000)
来模拟两秒钟的网络延迟,这样可以看到
emptyTemplate
中的内容。
Data Service
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class MyDataService : DataService
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
{
static List<Entry> _data;
static int _nextId;
static object _dataLock = new object();
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
private static List<Entry> Data
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
get
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_data == null)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
lock (_dataLock)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (_data == null)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
System.Threading.Thread.Sleep(2000);
_data = new List<Entry>();
_data.Add(new Entry(0, "ListView", "A control to display data using templates."));
_data.Add(new Entry(1, "Window", "A control to display dialogs."));
_data.Add(new Entry(2, "Weather", "A control to display local weather."));
_nextId = 3;
}
}
}
return _data;
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectMethod(DataObjectMethodType.Delete)]
public void DeleteRow(int id)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
foreach (Entry row in _data)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (row.Id == id)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
lock (_dataLock)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
_data.Remove(row);
}
break;
}
}
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectMethod(DataObjectMethodType.Select)]
public Entry[] SelectRows()
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return MyDataService.Data.ToArray();
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectMethod(DataObjectMethodType.Insert)]
public Entry InsertRow(string name, string description)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Entry newRow;
lock (_dataLock)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
newRow = new Entry(_nextId++, name, description);
_data.Add(newRow);
}
return newRow;
}
![InBlock.gif](/Images/OutliningIndicators/InBlock.gif)
[DataObjectMethod(DataObjectMethodType.Update)]
public void UpdateRow(Entry updateRow)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
foreach (Entry row in _data)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (row.Id == updateRow.Id)
![ExpandedSubBlockStart.gif](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
row.Name = updateRow.Name;
row.Description = updateRow.Description;
break;
}
}
}
}
然后,在
ASP.NET
中加入必须的标记,控件以及
ItemView
的模版。我们需要添加如下五部分的脚本:
- Atlas服务器端控件ScriptManager。所有的Atlas页面中都需要包含这个控件以装载Atlas所必须的JavaScript文件。
- id为detailsView的<div>,将被Atlas用来输出渲染后的内容。
- 导航部分,用于在在客户端集合中导航,以显示集合中不同的记录。
- 命令部分,用于修改,添加,删除记录(在客户端),并且提交到服务器。
- 模版部分,用于指定相应的ItemView模版。所有的模版将被置于一个隐藏的div中,这样不会在页面上显示出来。
<!--
ScriptManager
-->
<
atlas:ScriptManager
runat
="server"
ID
="scriptManager"
/>
![None.gif](/Images/OutliningIndicators/None.gif)
<!--
Element for ItemView (container)
-->
<
div
id
="detailsView"
>
</
div
>
![None.gif](/Images/OutliningIndicators/None.gif)
<!--
Navigators
-->
<
input
type
="button"
id
="previousButton"
value
="<"
title
="Go to previous row"
/>
<
span
id
="rowIndexLabel"
></
span
>
<
input
id
="nextButton"
type
="button"
value
=">"
title
="Go to next row"
/>
|
![None.gif](/Images/OutliningIndicators/None.gif)
<!--
Commands
-->
<
input
type
="button"
id
="addButton"
value
="New"
title
="Create a new row"
/>
<
input
type
="button"
id
="delButton"
value
="Delete"
title
="Delete the current row"
/>
|
<
input
type
="button"
id
="saveButton"
value
="Save"
title
="Save all pending changes"
/>
<
input
type
="button"
id
="refreshButton"
value
="Refresh"
title
="Discard pending changes and get the latest data from the server"
/>
![None.gif](/Images/OutliningIndicators/None.gif)
<!--
Templates
-->
<
div
style
="visibility: hidden; display: none"
>
<
div
id
="detailsTemplate"
>
Name:
<
input
id
="nameField"
size
="30"
/><
br
/>
Description:
<
br
/>
<
textarea
id
="descriptionField"
rows
="4"
cols
="40"
></
textarea
><
br
/>
</
div
>
<
div
id
="emptyTemplate"
>
Getting Data![dot.gif](https://www.cnblogs.com/Images/dot.gif)
</
div
>
</
div
>
最后需要做的是在页面上添加Atlas脚本。
下面是DataSource的脚本:
<
dataSource
id
="dataSource"
serviceURL
="MyDataService.asmx"
autoLoad
="true"
/>
下面是
ItemView
的脚本。我们将绑定上面的
DataSource
控件作为数据源,并且将
ItemView
的
enabled
属性绑定到
DataSource
的
isReady
属性上,以期在数据源没有装载完成前禁用
ItemView
。同样为
ItemView
定义了
itemTemplate
和
emptyTemplate
。
<
itemView
id
="detailsView"
>
<
bindings
>
<
binding
dataContext
="dataSource"
dataPath
="data"
property
="data"
/>
<
binding
dataContext
="dataSource"
dataPath
="isReady"
property
="enabled"
/>
</
bindings
>
<
itemTemplate
>
<
template
layoutElement
="detailsTemplate"
>
<
textBox
id
="nameField"
>
<
bindings
>
<
binding
dataPath
="Name"
property
="text"
direction
="InOut"
/>
</
bindings
>
</
textBox
>
<
textBox
id
="descriptionField"
>
<
bindings
>
<
binding
dataPath
="Description"
property
="text"
direction
="InOut"
/>
</
bindings
>
</
textBox
>
</
template
>
</
itemTemplate
>
<
emptyTemplate
>
<
template
layoutElement
="emptyTemplate"
/>
</
emptyTemplate
>
</
itemView
>
下面是导航部分的脚本。我们提供了一个label用来显示当前的记录编号(记录index加上1,使用了Atlas的Add transformer。关于Atlas transformer,您可以参考:在ASP.NET Atlas中创建自定义的Transformer )。还提供了前后移动记录的导航按钮(通过使用Atlas的InvokeMethod action调用相应的ItemView的方法)。
<
button
id
="previousButton"
>
<
bindings
>
<
binding
dataContext
="detailsView"
dataPath
="canMovePrevious"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="detailsView"
method
="movePrevious"
/>
</
click
>
</
button
>
![None.gif](/Images/OutliningIndicators/None.gif)
<
label
id
="rowIndexLabel"
>
<
bindings
>
<
binding
dataContext
="detailsView"
dataPath
="dataIndex"
property
="text"
transform
="Add"
/>
</
bindings
>
</
label
>
![None.gif](/Images/OutliningIndicators/None.gif)
<
button
id
="nextButton"
>
<
bindings
>
<
binding
dataContext
="detailsView"
dataPath
="canMoveNext"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="detailsView"
method
="moveNext"
/>
</
click
>
</
button
>
下面是命令部分的脚本。这里我们能够在客户端添加/删除记录,并将改变提交给服务器或者放弃提交。
<
button
id
="addButton"
>
<
bindings
>
<
binding
dataContext
="dataSource"
dataPath
="isReady"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="detailsView"
method
="addItem"
/>
</
click
>
</
button
>
![None.gif](/Images/OutliningIndicators/None.gif)
<
button
id
="delButton"
>
<
bindings
>
<
binding
dataContext
="dataSource"
dataPath
="isReady"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="detailsView"
method
="deleteCurrentItem"
/>
</
click
>
</
button
>
![None.gif](/Images/OutliningIndicators/None.gif)
<
button
id
="saveButton"
>
<
bindings
>
<
binding
dataContext
="dataSource"
dataPath
="isDirtyAndReady"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="dataSource"
method
="save"
/>
</
click
>
</
button
>
![None.gif](/Images/OutliningIndicators/None.gif)
<
button
id
="refreshButton"
>
<
bindings
>
<
binding
dataContext
="dataSource"
dataPath
="isReady"
property
="enabled"
/>
</
bindings
>
<
click
>
<
invokeMethod
target
="dataSource"
method
="load"
/>
</
click
>
</
button
>
大功告成,可以在浏览器中测试了。
装载中:
![itemview1.JPG](https://i-blog.csdnimg.cn/blog_migrate/a8483c3ff1c15ae25c7ebd3a55a0550b.jpeg)
装载完成:
![itemview2.JPG](https://i-blog.csdnimg.cn/blog_migrate/6a4ffb586f0e7f953c6558d2347ab488.jpeg)
记录间导航:
![itemview3.JPG](https://i-blog.csdnimg.cn/blog_migrate/3623967f46c761a486c2457a00139b4e.jpeg)
修改并保存:
![itemview4.JPG](https://i-blog.csdnimg.cn/blog_migrate/c57f661905d63f61b75cb4d2f073775e.jpeg)
上述示例代码可以在此处下载:http://files.cnblogs.com/dflying/AtlasItemViewDemo.zip