Yok

苦海无涯,回头是岸啊

利用反射实现ASP.NET控件和数据实体之间的双向绑定,并且在客户端自动验证输入的内容是否合法

首先请原谅我蹩脚的中文...玩电脑太多都不太会说话了,但愿大家看的明白

ASP.NET的UI不像做Winform那么容易,设个DataSource和DataField就什么都搞定了.虽然提供了<%#%>这样形式的绑定,但是这种绑定是单向的,只能从数据源赋值给控件,无法把控件的内容写回数据源.所以,在保存数据时得一条一条写,还得处理null,类型转换什么的.例如
anObject.AnIntProperty =  Convert.ToInt32(aControl.Text == "" ? aControl.Text  : "0"); //用数据实体的话
或者
aDatarow["AnIntField"] =  Convert.ToInt32(aControl.Text == "" ? aControl.Text  : "0"); //用datarow的话
有时一张表单几十个字段,这样写准会疯的 >_<

于是我利用反射做了一个东西,实现了让控件显示数据实体(我惯用o-r mapping而不是DataSet/DataRow,当然DataRow也能用类似的方式去搞)的内容和把控件的内容赋回给数据实体,然后,顺便把数据合法性验证也做进去了(反射性能损耗大,不干多点东西心里不平衡啊)

在我的BindingManager类中约定,凡是"_"结尾的控件将会被处理,这些控件会和实体类相对应的属性自动关联起来.通过设置PrefixLength的值指定从控件名的第几个字符开始匹配实体类属性,例如我习惯用3个字符做控件前缀,于是设PrefixLength为3,和Name属性关联的控件名就形如txtName_.然后调用GetEntityValues(Page,theObject)和SetEntityValue(Page,theObject)来实现控件和数据实体之间的绑定.

至于"顺便"做的合法性验证的功能,首先确保了控件输入的内容符合实体属性的类型,这是自动完成的,例如一个int属性对应的控件不能填写字母.如果有更多的要求,例如用正则表达式,不允许空值,或者在出错时给用户更详细的提示,则给实体的属性加上ValidateAttribute后就可以实现.

这是一个我写的Demo的其中一部分:Person类,其中有各种不同类型的属性.可以看到ValidateAttribute指定了Name不可空,描述为"姓名",这样,当 txtName_.Text 是空值时提交数据,将会弹出提示"姓名不能为空".而Id则规定了要输入现在新身份证的格式,如果不符合的话则提示"身份证号码格式不正确".另外,Sex是个自定义的类.得做个针对他的TypeConverter,然后给Sex类加上TypeConverterAttribute才可能被正确的处理.


    public class Person
    
{
        
public Person()
        
{
                
        }


        
string _name;
        
decimal _height;
        DateTime _birthday;
        Sex _sex;
        [Validate(AllowNull 
= false, Description = "姓名")]
        
public string Name 
        
{
            
get {return _name;}
            
set {_name = value;}
        }

        [Validate(Description 
= "身高")]
        
public decimal Height
        
{
            
get {return _height;}
            
set {_height = value;}
        }

        
string _id;
        [Validate(RegEx 
= "^\\d{17}(\\d|x)$", Description = "身份证号码")]
        
public string Id 
        
{
            
get {return _id;}
            
set {_id = value;}
        }

            
            
public DateTime Birthday
        
{
            
get {return _birthday;}
            
set {_birthday = value;}
        }


        
public Sex Sex 
        
{
            
get {return _sex;}
            
set {_sex = value;}
        }

    }

在使用Person类时,一行语句就能实现控件和数据间赋值.以下是一个aspx后台代码的片断:

        Person p 
= new Person();
        BindingManager bm 
= new BindingManager();
        
private void Page_Load(object sender, System.EventArgs e)
        
{

            
if (!IsPostBack) 
            
{
                
//validateForm()是客户端验证控件合法性时调用的函数                       
                Button1.Attributes["onclick"= "return validateForm();"
                
//给p随便设点值
                p.Name = "Yok";
                p.Height 
= 170;
                p.Sex 
= Sex.Male;
                p.Birthday 
= new DateTime(19801121);
                
//这样就可以让控件显示p的内容                
                bm.GetEntityValues(Page, p);
            }

        }


        
private void Button1_Click(object sender, System.EventArgs e)
        
{
            
//把值赋给实体
            bm.SetEntityValues(Page, p);
            
//这时p已经从控件获得各个属性的值.Write出来看一下是否正确
            Response.Write("Name = " + p.Name + "<br>");
            Response.Write(
"Height = " + p.Height + "<br>");
            Response.Write(
"Birthday = " + p.Birthday.ToShortDateString() + "<br>");
            Response.Write(
"Id = " + p.Id + "<br>");
            Response.Write(
"Sex = " + p.Sex.ToString() + "<br>");
        }



不说了,我的代码应该比我的文字好懂

posted on 2004-11-23 22:24  Yok  阅读(4777)  评论(29编辑  收藏  举报

导航