iT堂首页 | iT资讯 | 网络资源 | 站长频道 | 知识堂 | iT学堂
alexa排名查询 | iT堂工具箱
发新话题
打印

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

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

一、先说一下表单控件要实现的功能吧。
     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:“单列”形式的表格

TOP


图2 :两列的形式。


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



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


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



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



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


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

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

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




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

TOP




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

     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

TOP

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