您的位置:首页 > 产品设计 > UI/UE

【实现】表单控件的UI布局,实现方式

2008-08-10 10:24 417 查看
一、先说一下表单控件要实现的功能吧。



1、绘制UI,包括表格(Table)的绘制,也就是TR 、TD,TR是多少行,TD是有多少列;包括子控件的控件,TextBox、DropDownList、CheckBoxList等控件的加载、描述(宽度、最大字符数、填充item)等。



2、提取用户输入的数据,拼接参数化的SQL语句,给存储过程的参数赋值。



3、把存储过程的名称(参数化SQL)、存储过程的参数,通过“我的数据访问函数库”提交给数据库执行。



4、在显示数据和修改数据的时候,可以从数据库显示数据进行控件绑定。就是显示数据。



5、支持两种保存数据的方式:参数化SQL和存储过程。



6、可以向SQL Server2000、SQL Server2005、Access、Excel数据库里添加、修改数据,已测试。



7、可以向OleDb、ODBC连接的数据库添加、修改数据,只对Access、Excel进行了测试,没有测试其他的数据库。



8、表格的样式交给CSS来控制。



9、可以单列、也可以多列(通过属性来控制),在“多列”显示的时候,如果最后一行字段不够的话,可以自动补充TD。见图7。



表单控件的有点:



1、自动生成子控件(文本框、下拉列表框等)

2、当数据库的字段有变化的时候,只需要修改一个地方就可以搞定,不用到许多的地方修改。

3、不用做过多的测试,因为每一个项目、每一个添加、修改的地方都在测试这个控件,到最后就可以不用测试了。



二、说一下表格的绘制,也就是TR TD的处理。可以支持四种显示方式。

1、单列。所有的字段都在“一列”里面显示。图1

2、多列。 图2 、 图3

3、一个字段占多个TD。图4 、 图5

4、多个字段占用一个TD。图6

5、可以综合应用。图8



图片演示:








图1:“单列”形式的表格





图2 :两列的形式。





图3:四列的形式。这个用在查询的时候,也就是说给查询控件准备的。








图4:一个字段占用多个TD,居住地区和备注占了“两列”,标签占用了一个TD,控件占用了三个TD。





图5:三列,一个字段占用多个TD,居住地区和备注占了“三列”,标签占用了一个TD,控件占用了五个TD。







图6:多个字段挤在一个TD里面。姓名、性别在一行,籍贯、省、市在一行。性别、省、市前面的空格数量可以控制,也就是说可以控制和前一个控件的距离。








图7:最后一行只有两个字段,还少两个TD,这个控件会自动补充,不会像DataList那样,少了就不管了。这里的a、b是测试用,正式的时候会用  替换。






图8:综合应用:“两列”的表格,省、市两个字段挤在一个TD里面,备注独占“两列”。



三、根据配置信息来显示表格的代码和说明。



1、配置信息(描述信息)

配置信息分别放在11个表里面,分别是表的描述、字段的描述、模块信息的描述、列表页面需要的字段和描述、表单页面需要的字段和描述、查询功能需要的字段和描述等。关联关系如下图:(这个只是通过视图来表示一下关系。)









再来详细看一下表单控件需要的配置信息。









这个图好像有点乱。总之就是根据这些信息,显示出来右上角的那个表格的。



2、BaseColumnsInfo类 和 Dictionary

BaseColumnsInfo的一个实例记录一个字段的描述信息,多个字段就需要放在Dictionary里面,我们先写一个函数用来加载配置信息。



然后我们就可以在 CreateChildControls 里面通过BaseColumnsInfo的信息来进行表格绘制和加载子控件了。






private void aa()






{


Dictionary<int, BaseColumnsInfo> dic_BaseCols = new Dictionary<int, GridColumnsInfo>();


//加载信息的函数略




//定义接口,通过接口操作子控件


IGetControlValue iControl = null;


Control tmpControl = null; //子控件




BaseColumnsInfo bInfo;




//开始绘制表格


this.Controls.Add(new LiteralControl("<Table rules=/"all/" class=/"css_Form/">"));




Int32 index = 0; //用于多列的设置




//遍历Dictionary,绘制表格


foreach (KeyValuePair<int, BaseColumnsInfo> info in dic_BaseCols)






{


bInfo = (BaseColumnsInfo)info.Value;






生成需要的子控件#region 生成需要的子控件


switch (bInfo.ControlKind)






{


case "201": //单行文本框


tmpControl = new myTextBox(); break;




//其他控件略




}


#endregion




iControl = (IGetControlValue)tmpControl; //定义接口,通过接口操作子控件


tmpControl.ID = "c_" + bInfo.ColumnID; //设置ID


iControl.ShowMe(bInfo); //让子控件自己描绘自己






显示字段#region 显示字段


this.Controls.Add(new LiteralControl("<TR>"));


this.Controls.Add(new LiteralControl("<TD align=/"right/" width=/"200px/">"));


this.Controls.Add(new LiteralControl(bInfo.ColName));


this.Controls.Add(new LiteralControl(":</TD>"));


this.Controls.Add(new LiteralControl("<TD>"));


this.Controls.Add(tmpControl); //加载子控件


this.Controls.Add(new LiteralControl("</TD>"));


this.Controls.Add(new LiteralControl("</TR>"));


#endregion






}


this.Controls.Add(new LiteralControl("</Table>"));


}








这是一个简化后的代码,只能实现“单列”的表格。这样写可以比较清晰的把思路显示出来。下面的是真正实现多行多列的代码,看起来就比较费解了。








Code


protected override void CreateChildControls()






{


base.CreateChildControls();


ShowForm();




//base.Page.Response.Write(DateTime.Now);


}






/**//// <summary>


/// 绑定数据


/// </summary>


public override void DataBind()






{


if ((base.Site != null) && base.Site.DesignMode)






{


//设计模式,退出


return;


}


}






显示表单#region 显示表单




/**//// <summary>


/// 显示表单


/// </summary>


public void ShowForm()






{


if ((base.Site != null) && base.Site.DesignMode)






{


//设计模式,退出


return;


}






加载配置信息#region 加载配置信息


if (dic_BaseCols == null)


LoadBaseColumnsInfo();




//没有配置信息,退出


if (dic_BaseCols == null)






{


CommandClass.MsgBox("没有设置配置信息", true);


return;


}


#endregion




//定义接口,通过接口操作子控件


IGetControlValue iControl = null;


Control tmpControl = null;




BaseColumnsInfo bInfo;




//开始绘制表格


this.Controls.Add(new LiteralControl("<Table rules=/"all/" class=/"css_Form/">"));




Int32 index = 0; //用于多列的设置




//循环配置信息


foreach (KeyValuePair<int, BaseColumnsInfo> info in dic_BaseCols)






{


bInfo = (BaseColumnsInfo)info.Value;






加载需要的子控件,有待完善#region 加载需要的子控件,有待完善


switch (bInfo.ControlKind)






{


case "201": //单行文本框


tmpControl = new myTextBox(); break;




case "205": //下拉列表框


//tmpControl = new JYKDropDownList();


break;




}


#endregion




iControl = (IGetControlValue)tmpControl; //定义接口,通过接口操作子控件


tmpControl.ID = "c_" + bInfo.ColumnID ; //设置ID


iControl.ShowMe(bInfo); //让子控件自己描绘自己






显示字段#region 显示字段


SetStartTR(index, bInfo); //判断是否显示<TR>




//添加到表单控件里


SetStartTD(bInfo); //设置开始的TD


this.Controls.Add(new LiteralControl(bInfo.ColName));





index += SetTDcolspan(bInfo); //设置中间的TD,一个字段占用几个TD


this.Controls.Add(tmpControl);


SetEndTD(bInfo); //设置结束的TD





SetEndTR(index,bInfo); //判断是否显示</TR> ,有了</TR>就相当于换行了




#endregion




index++;




if (index >= TDColumns) index = 0;




//iControl.ControlValue = "sss"; //赋值测试




}




if (index != 0 && index <= TDColumns - 1)






{


//表格不满需要补充TD


for (Int32 i = index; i < TDColumns; i++)






{


this.Controls.Add(new LiteralControl("<TD>a</TD>"));


this.Controls.Add(new LiteralControl("<TD>b</TD>"));


}


this.Controls.Add(new LiteralControl("</TR>"));


}


this.Controls.Add(new LiteralControl("</Table>"));




}


#endregion






设置table#region 设置table






设置开始的TD#region 设置开始的TD




/**//// <summary>


/// 设置开始的TD


/// </summary>


/// <param name="bInfo">字段的描述</param>


private void SetStartTD(BaseColumnsInfo bInfo)






{


if (bInfo.clearTDStart > 0)






{


//需要合并到上一个TD里面,不显示中间的TD


string s = " ";


for (int i = 1; i < bInfo.clearTDStart; i++)


s += " ";




this.Controls.Add(new LiteralControl(s));


}


else






{


this.Controls.Add(new LiteralControl("<TD align=/"right/" width=/"200px/">"));


}




}


#endregion






设置结束的TD#region 设置结束的TD




/**//// <summary>


/// 设置一个字段占用几个TD


/// </summary>


/// <param name="bInfo">字段的描述</param>


private void SetEndTD(BaseColumnsInfo bInfo)






{


if (bInfo.clearTDEnd > 0)






{


//需要合并下面的TD,不显示结束的TD


}


else






{


//不需要合并下面的TD,显示结束的TD


this.Controls.Add(new LiteralControl("</TD>"));


}




}


#endregion






设置一个字段占用几个TD#region 设置一个字段占用几个TD




/**//// <summary>


/// 设置一个字段占用几个TD


/// </summary>


/// <param name="bInfo">字段的描述</param>


private Int32 SetTDcolspan(BaseColumnsInfo bInfo)






{


if (bInfo.clearTDStart > 0)






{


//需要合并到上一个TD里面,不显示中间的TD


this.Controls.Add(new LiteralControl(":"));


return -1;


}




else






{


//不合并到上一个TD,显示中间的TD


this.Controls.Add(new LiteralControl(":</TD>"));


if (bInfo.TDColspan >= 2)






{


//判断一个字段需要占用几个TD


this.Controls.Add(new LiteralControl("<TD colspan=/"" + (bInfo.TDColspan * 2 - 1).ToString() + "/">"));


return bInfo.TDColspan - 1;


}


else






{


this.Controls.Add(new LiteralControl("<TD>"));


return 0;


}


}


}


#endregion






设置是否显示开始的 TR#region 设置是否显示开始的 TR




/**//// <summary>


/// 设置是否显示开始的 TR


/// </summary>


/// <param name="index">循环的序号</param>


/// <param name="bInfo">字段的描述</param>


private void SetStartTR(Int32 index, BaseColumnsInfo bInfo)






{


if (bInfo.clearTDStart > 0)






{


//合并到上一个TD,不显示TR


}


else






{


if (index == 0)


this.Controls.Add(new LiteralControl("<TR>"));


}


}


#endregion






设置是否显示结束的 TR#region 设置是否显示结束的 TR




/**//// <summary>


/// 设置是否显示结束的 TR


/// </summary>


/// <param name="index">循环的序号</param>


/// <param name="bInfo">字段的描述</param>


private void SetEndTR(Int32 index, BaseColumnsInfo bInfo)






{


if (bInfo.clearTDEnd > 0)






{


//合并下一个TD,不显示TR


}


else






{


if (index == TDColumns - 1)


this.Controls.Add(new LiteralControl("</TR>"));


}


}


#endregion






最后就是获取用户输入的信息的代码,由于采用了接口,所以代码就很简单了。






Code


public void GetInputValue()






{


IGetControlValue ControlValue = null; //取值的接口





BaseColumnsInfo bInfo;




string tmpDataValue = ""; //临时存放数据




foreach (KeyValuePair<int, BaseColumnsInfo> info in dic_BaseCols)






{


bInfo = (BaseColumnsInfo)info.Value;




ControlValue = (IGetControlValue)this.FindControl("c_" + bInfo.ColumnID);




tmpDataValue = ControlValue.GetControlValue("1");






验证数据是否符合字段的要求#region 验证数据是否符合字段的要求


#endregion




bInfo.DataValue = tmpDataValue;


}


}




添加存储过程的参数的代码






Code

private void AddParameter()

{

//根据配置信息添加存储过程(参数化SQL语句)需要的参数。

BaseColumnsInfo bInfo;

dal.LoadParameter();

foreach (KeyValuePair<int, BaseColumnsInfo> info in dic_BaseCols)

{

bInfo = (BaseColumnsInfo)info.Value;

switch (bInfo.ColType)

{

case "bigint":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, Int64.Parse(bInfo.DataValue));

break;

case "tinyint":

case "smallint":

case "int":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName , Int32.Parse(bInfo.DataValue));

break;

case "uniqueidentifier":

case "char":

case "nchar":

case "varchar":

case "nvarchar":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, bInfo.DataValue,bInfo.ColSize);

break;

case "text":

case "ntext":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, bInfo.DataValue);

break;

case "real":

case "float":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, double.Parse(bInfo.DataValue));

break;

case "numeric":

case "smallmoney":

case "money":

case "decimal":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, decimal.Parse(bInfo.DataValue));

break;

case "smalldatetime":

case "datetime":

dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, DateTime.Parse(bInfo.DataValue));

break;

default : //

//dal.ParameterMgr.AddNewParameter("@" + bInfo.ColSysName, Int32.Parse(bInfo.DataValue));

break;

}

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: