Flex对象与组件的数据动态双向绑定

本文介绍了一个Flex应用程序中实现Entity对象与Display对象之间数据双向动态绑定的方法。支持多种组件,包括TextInput、DateField和ComboBox等。通过反射机制获取MXML信息,并实现属性的自动绑定。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用于Flex中Entity对象与Display对象之间的数据双向动态绑定,支持TextInput、DateField、ComboBox。

  • package controller.utils{   
  •     import com.ericfeminella.collections.HashMap;   
  •     import com.ericfeminella.collections.IMap;   
  •        
  •     import flash.display.DisplayObject;   
  •     import flash.utils.describeType;   
  •        
  •     import mx.binding.utils.BindingUtils;   
  •     import mx.binding.utils.ChangeWatcher;   
  •     import mx.events.PropertyChangeEvent;   
  •     import mx.utils.ObjectProxy;   
  •        
  •     /**  
  •      * @Description: BindingHelper  
  •      * @author Lyon  
  •      */  
  •     public class BindingHelper{   
  •         /**  
  •          * 目前支持的绑定组件类型   
  •          */        
  •         private static const typeMap: Object = {    'mx.controls::TextInput' : 'text',   
  •                                                                         'mx.controls::DateField' : 'selectedDate',   
  •                                                                         'mx.controls::ComboBox': 'selectedItem'  
  •                                                                         };         
  •         /**  
  •          * 存储监控对象的句柄  
  •          * key: entityObj  
  •          * value: ChangeWatcher  
  •          */        
  •         private static var handleList:IMap = new HashMap();   
  •            
  •         /**    
  •          * 对象与组件的数据动态双向绑定    
  •          * @param entityObj   Entity Object  
  •          * @param displayObj  MX控件  
  •          * @param type              控件类型,如:'mx.controls::TextInput'  
  •          * @exclude                 需要排除的property  
  •          * @bidirectional           是否做双向绑定(如果为false,那么只做entity到displayObject的绑定)  
  •          * @param commitOnly  
  •          */    
  •         public static function bidirectionalDataBind(   
  •                                     entityObj:Object,    
  •                                     displayObj:DisplayObject,   
  •                                     exclude:Array=null,   
  •                                     bidirectional:Boolean=true,   
  •                                     type:String='ALL',                                     
  •                                     commitOnly:Boolean = false):void{   
  •             if(type == 'ALL'){   
  •                 for (var typeTmp:String in typeMap){   
  •                     bidirectionalDataBind(entityObj,displayObj,exclude,bidirectional,typeTmp,commitOnly);   
  •                 }   
  •             }else{   
  •                 //通过反射机制取出当前MXML中的信息   
  •                 var instanceInfo:XML=flash.utils.describeType(displayObj);   
  •                 var properties:XMLList =instanceInfo..accessor.(@type==type);   
  •                 var tmpObj:ObjectProxy;   
  •     //          trace(instanceInfo..accessor.(@type==type));   
  •        
  •                 var prop:String = BindingHelper.getSiteProp(type);   
  •        
  •                 for each(var propertyInfo:XML in properties){   
  •                     //此处取出的为textinput的id   
  •                     var proName:String = propertyInfo.@name;   
  •                        
  •                     // 需要排除的property   
  •                     if(exclude != null && exclude.indexOf(proName) != -1){   
  •                         continue;   
  •                     }   
  •                        
  •                     // 检查该property是否存在   
  •                     if(BeanUtils.checkPropertyExist(entityObj,proName) == false){   
  •                         continue;   
  •                     }   
  •                        
  •                     try{   
  •                         // ComboBox   
  •                         if(type == 'mx.controls::ComboBox'){   
  •                             if(handleList.getValue(entityObj) == null){   
  •                                 handleList.put(entityObj,new HandleObject(entityObj));   
  •                             }   
  •                                
  •                             var cw:ChangeWatcher = ChangeWatcher.watch(entityObj,proName,setData);   
  •                             HandleObject(handleList.getValue(entityObj)).addChangeWatcher(proName,cw);   
  •                                
  •                             BindingUtils.bindProperty(entityObj,proName,DisplayObject(displayObj[proName]),prop,commitOnly);   
  •                         }else{   
  •                             BindingUtils.bindProperty(DisplayObject(displayObj[proName]),prop,entityObj,proName,commitOnly);   
  •                             if(bidirectional == true)   
  •                                 BindingUtils.bindProperty(entityObj,proName,DisplayObject(displayObj[proName]),prop,commitOnly);   
  •                         }   
  •                      }catch(err:Error){   
  •                         trace(err.message);   
  •                     }   
  •                 }   
  •             }   
  •         }   
  •            
  •         /**   
  •          * 清空监控对象的句柄集合  
  •          */        
  •         public static function clean():void{   
  •             if(handleList != null){   
  •                 for each(var ho:Object in handleList.getValues()){   
  •                     HandleObject(ho).clean();   
  •                 }   
  •                    
  •                 handleList.clear();   
  •             }   
  •         }   
  •            
  •         /**  
  •          * 监听ComboBox事件的变化  
  •          * @param obj  
  •          */  
  •         private static function setData(obj:PropertyChangeEvent):void{   
  •             if(obj.newValue == null){   
  •                 return;   
  •             }   
  •             var ho:HandleObject = handleList.getValue(obj.source);             
  •             var cw:ChangeWatcher = ho.getChangeWatcher(obj.property);   
  •                
  •             if(obj.newValue is String){   
  •                 cw.unwatch();   
  •                 cw = ChangeWatcher.watch(obj.source,obj.property,setData);   
  •                 ho.addChangeWatcher(obj.property,cw);   
  •                 return;   
  •             }else{     
  •                 var code:Object = obj.newValue.code;   
  •                 obj.source[obj.property] = code;   
  •             }   
  •         }   
  •            
  •         /**  
  •          * 返回组件TYPE对应的需要填充的属性名称   
  •          * @param type  
  •          * @return   
  •          */        
  •         private static function getSiteProp(type: String): String{   
  •             for (var name:String in typeMap){   
  •                 if(name == type){   
  •                     return typeMap[name];   
  •                 }   
  •             }   
  •             return null;   
  •         }   
  •     }   
  • }   
  •   
  •  import mx.binding.utils.ChangeWatcher;   
  •  import com.ericfeminella.collections.IMap;   
  • import com.ericfeminella.collections.HashMap;   
  • internal class HandleObject{   
  •         private var entityObject:*;   
  •         private var properityList:IMap;   
  •            
  •         public function HandleObject(entityObject:*):void{   
  •             this.entityObject = entityObject;   
  •             properityList = new HashMap();   
  •         }   
  •            
  •         public function addChangeWatcher(propName:Object, cw:ChangeWatcher):void{   
  •             properityList.put(propName,cw);   
  •         }   
  •            
  •         public function getChangeWatcher(propName:Object):ChangeWatcher{   
  •             return properityList.getValue(propName);   
  •         }   
  •            
  •         public function clean():void{   
  •             for each(var cw:Object in properityList.getValues()){   
  •                 ChangeWatcher(cw).unwatch();   
  •             }   
  •                
  •             properityList.clear();   
  •         }   
  •     }  
  • package controller.utils{
    	import com.ericfeminella.collections.HashMap;
    	import com.ericfeminella.collections.IMap;
    	
    	import flash.display.DisplayObject;
    	import flash.utils.describeType;
    	
    	import mx.binding.utils.BindingUtils;
    	import mx.binding.utils.ChangeWatcher;
    	import mx.events.PropertyChangeEvent;
    	import mx.utils.ObjectProxy;
    	
    	/**
    	 * @Description: BindingHelper
    	 * @author Lyon
    	 */
    	public class BindingHelper{
    		/**
    		 * 目前支持的绑定组件类型 
    		 */		
    		private static const typeMap: Object = {	'mx.controls::TextInput' : 'text',
    																		'mx.controls::DateField' : 'selectedDate',
    																		'mx.controls::ComboBox': 'selectedItem'
    																		};		
    		/**
    		 * 存储监控对象的句柄
    		 * key: entityObj
    		 * value: ChangeWatcher
    		 */		
    		private static var handleList:IMap = new HashMap();
    		
    		/**  
             * 对象与组件的数据动态双向绑定  
             * @param entityObj   Entity Object
             * @param displayObj  MX控件
             * @param type       	 	控件类型,如:'mx.controls::TextInput'
             * @exclude					需要排除的property
             * @bidirectional      		是否做双向绑定(如果为false,那么只做entity到displayObject的绑定)
             * @param commitOnly
             */	
    		public static function bidirectionalDataBind(
    									entityObj:Object, 
    									displayObj:DisplayObject,
    									exclude:Array=null,
    									bidirectional:Boolean=true,
    									type:String='ALL',									
    									commitOnly:Boolean = false):void{
    			if(type == 'ALL'){
    				for (var typeTmp:String in typeMap){
    					bidirectionalDataBind(entityObj,displayObj,exclude,bidirectional,typeTmp,commitOnly);
    				}
    			}else{
    				//通过反射机制取出当前MXML中的信息
    				var instanceInfo:XML=flash.utils.describeType(displayObj);
    				var properties:XMLList =instanceInfo..accessor.(@type==type);
    				var tmpObj:ObjectProxy;
    	//			trace(instanceInfo..accessor.(@type==type));
    	
    				var prop:String = BindingHelper.getSiteProp(type);
    	
    				for each(var propertyInfo:XML in properties){
    					//此处取出的为textinput的id
    				  	var proName:String = propertyInfo.@name;
    				  	
    				  	// 需要排除的property
    				  	if(exclude != null && exclude.indexOf(proName) != -1){
    				  		continue;
    				  	}
    				  	
    				  	// 检查该property是否存在
    				  	if(BeanUtils.checkPropertyExist(entityObj,proName) == false){
    				  		continue;
    				  	}
    				  	
    				  	try{
    					  	// ComboBox
    					  	if(type == 'mx.controls::ComboBox'){
    					  		if(handleList.getValue(entityObj) == null){
    					  			handleList.put(entityObj,new HandleObject(entityObj));
    					  		}
    					  		
    							var cw:ChangeWatcher = ChangeWatcher.watch(entityObj,proName,setData);
    							HandleObject(handleList.getValue(entityObj)).addChangeWatcher(proName,cw);
    							
    							BindingUtils.bindProperty(entityObj,proName,DisplayObject(displayObj[proName]),prop,commitOnly);
    					  	}else{
    					  		BindingUtils.bindProperty(DisplayObject(displayObj[proName]),prop,entityObj,proName,commitOnly);
    							if(bidirectional == true)
    								BindingUtils.bindProperty(entityObj,proName,DisplayObject(displayObj[proName]),prop,commitOnly);
    					  	}
    					 }catch(err:Error){
    				  		trace(err.message);
    				  	}
    				}
    			}
    		}
    		
    		/** 
    		 * 清空监控对象的句柄集合
    		 */		
    		public static function clean():void{
    			if(handleList != null){
    				for each(var ho:Object in handleList.getValues()){
    					HandleObject(ho).clean();
    				}
    				
    				handleList.clear();
    			}
    		}
    		
    		/**
    		 * 监听ComboBox事件的变化
    		 * @param obj
    		 */
    		private static function setData(obj:PropertyChangeEvent):void{
    			if(obj.newValue == null){
    				return;
    			}
    			var ho:HandleObject = handleList.getValue(obj.source);			
    			var cw:ChangeWatcher = ho.getChangeWatcher(obj.property);
    			
    			if(obj.newValue is String){
    				cw.unwatch();
    				cw = ChangeWatcher.watch(obj.source,obj.property,setData);
    				ho.addChangeWatcher(obj.property,cw);
    				return;
    			}else{	
    				var code:Object = obj.newValue.code;
    				obj.source[obj.property] = code;
    			}
    		}
    		
    		/**
    		 * 返回组件TYPE对应的需要填充的属性名称 
    		 * @param type
    		 * @return 
    		 */		
    		private static function getSiteProp(type: String): String{
    			for (var name:String in typeMap){
    				if(name == type){
    					return typeMap[name];
    				}
    			}
    			return null;
    		}
    	}
    }
    
    import mx.binding.utils.ChangeWatcher;
    import com.ericfeminella.collections.IMap;
    import com.ericfeminella.collections.HashMap;
    internal class HandleObject{
    		private var entityObject:*;
    		private var properityList:IMap;
    		
    		public function HandleObject(entityObject:*):void{
    			this.entityObject = entityObject;
    			properityList = new HashMap();
    		}
    		
    		public function addChangeWatcher(propName:Object, cw:ChangeWatcher):void{
    			properityList.put(propName,cw);
    		}
    		
    		public function getChangeWatcher(propName:Object):ChangeWatcher{
    			return properityList.getValue(propName);
    		}
    		
    		public function clean():void{
    			for each(var cw:Object in properityList.getValues()){
    				ChangeWatcher(cw).unwatch();
    			}
    			
    			properityList.clear();
    		}
    	}
    

     

  • package controller.utils{   
  •        
  •     import com.adobe.serialization.json.JSON;   
  •        
  •     import mx.collections.ArrayCollection;   
  •     import mx.utils.ObjectUtil;   
  •     import mx.utils.StringUtil;   
  •   
  •     /**  
  •      * @Description: Object Utils  
  •      * @author Lyon  
  •      */  
  •     public class BeanUtils{        
  •         /**  
  •          * 检查对象的property是否存在  
  •          * @param obj  
  •          * @param proName  
  •          * @return   
  •          */        
  •         public static function checkPropertyExist(targetObj:*, proName:String):Boolean{   
  •             if(targetObj as String    
  •                     || targetObj as int  
  •                     || targetObj as Date   
  •                     || targetObj as Number){   
  •                 return false;   
  •             }   
  •                
  •             var objInfo:Object = ObjectUtil.getClassInfo(targetObj);   
  •             for each(var name:String in objInfo.properties){   
  •                 if(name == proName){   
  •                     return true;   
  •                 }   
  •             }   
  •                
  •             return false;   
  •         }  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值