在Web上实现对Table中显示的列为用户可定制
本人结合在一个DoNet项目中的应用,讨论一实现方式
要求: 数据库中A表 有col1,col2,col3,col4,col5,col6
在列表界面上,可以通过点击"定制"按钮 来指定界面需要显示的column
本人在项目中的实现方式(附上了项目中部分代码供参考):
1.建立一张PLT_FIELDVISUAL表
字段:
OID
EntityType 可存储实体对象标识或表名或View的名称
FieldName
Tag 显示/隐藏标记 本人实践中是将 style='display:none' 写入
2.IBEntity 接口中增加
string[] getFieldsCN(); //字段对应的中文名
针对有些列始终不需要在List界面上显示,比如OID列,Contents列等那么可以采用如下的定义
columnsCN[0] = "[OID]"; 即加上[] 来表示不进行定制的列,始终不显示
string getEntityName(); //返回实体的名称
//虽然有getTableName()方法,但考虑到有些情况表名与Entity的名是不同的
//如表名:PLT_UserInfo 而Entity名为:UserInfo
3.具体的Entity类中对getFieldsCN(),getEntityName()方法做实现
4.列的选择(可重用)
显示:ShowColumn.aspx
获取实体类路径
根据实体类路径,构造对象
取得到传入实体的字段名
取得到传入实体的字段中文名
循环显示
checkbox value="列名" 列中文名
注意判断
if (columnCNName[i].IndexOf("[")>-1) //始终不在列表界面上显示的列
{
//只显示,没有checkbox
Response.Write("<td>" + StringLang.getEmptyString(columnName[i]) + "</td>");
Response.Write("<td>" + StringLang.getEmptyString(columnCNName[i]) + "</td>");
}
处理:Action.aspx
获取实体类路径
根据实体类路径,构造实体对象
得到传入实体的字段名
得到选中(指定显示)的字段名
首先清除PLT_FIELDVISUAL表中EntityType=实体对象标识的数据
condition1: 如果选择了显示列,将实体的字段名与选中的字段名比较,将没有选中的字段名写入
condition2: 如果没有选择显示列,则将实体的所有字段名写入PLT_FIELDVISUAL表
ShowColumn.aspx
//获取参数
strEntityPath = StringLang.getEmptyString(Request["entitypath"]).Trim();
entity = (IBEntity)CommonLang.getObject(strEntityPath);
columnName = entity.getFields(); //得到传入实体的字段名
columnCNName = entity.getFieldsCN(); //得到传入实体的字段中文名
5.List界面上显示的处理
利用.Net的Page可继承的机制
在IndexBasePage页面中根据不同的entity来构造其各列的显示状态
public Hashtable FieldVisual = null; //字段显示状态
/// <summary>
/// 将Entity的所有字段,放入Hashtable,以字段名为key,以字段的显示状态为value
/// 如果字段在PLT_FIELDVISUAL表中存在,则value取对应的PLT_FIELDVISUAL.Tag字段值
/// </summary>
/// <param name="entity"></param>
public void InitFieldVisual(IBEntity entity)
{
FieldVisual = new Hashtable();
string sSQL = "select * from PLT_FIELDVISUAL where EntityType=" + DBLang.getSqlStr(entity.getEntityName());
DataTable dt = DBFacade.RunSQLReturnDT(sSQL);
string strFieldKey = "";
string strTag = "";
for (int i = 0; i < entity.getFields().Length - 1; i++)
{
strFieldKey = entity.getFields()[i];
strTag = "";
for (int j = 0; j < dt.Rows.Count; j++)
{
if (dt.Rows[j]["FieldName"].Equals(strFieldKey))
{
strTag = StringLang.getEmptyString(dt.Rows[j]["Tag"]).Trim();
break;
}
}
FieldVisual.Add(strFieldKey, strTag);
}
}
这样可以在不同模块的Index.aspx中调用InitFieldVisual方法,传入不同的entity
A entity = new A();
InitFieldVisual(entity);
当然此处的Index.aspx 需要继承IndexBasePage
6.List界面的显示:
标题列
<td id='Title_col1' <%=FieldVisual[A.Field.COL1]%>>列名1</td>
<td id='Title_col1' <%=FieldVisual[A.Field.COL2]%>>列名2</td>
................
Value列
Response.Write("<td align='left' " + FieldVisual[A.Field.COL1] + ">" + dr[A.Field.COL2].ToString()+ " </td>");
Response.Write("<td align='left' " + FieldVisual[A.Field.COL2] + ">" + dr[A.Field.COL2].ToString()+ " </td>");
7.定制按钮客户端实现
<input type="button" value="定制" onclick="return(doConfigColumn('实体类路径,程序集名'));"/>
使用showModalDialog打开定制界面ShowColumn.aspx
//定制
function doConfigColumn(s_EntityPath){
var strReturnValue="";
strReturnValue=showModalDialog("ColumnVisual/ShowColumn.aspx?entitypath=" + s_EntityPath,"","dialogWidth:350px;dialogHeight:450px;center:yes;resizable:no;status:no;help:no");
if(strReturnValue=="ok"){
location.reload(); //回刷本页,同时更新显示的列
}
}
本功能的实现主要借助了PLT_FIELDVISUAL表,将不显示的列写入该表内,并在Tag字段写入HTML隐藏标签