Click here to Skip to main content
15,886,873 members
Articles / Programming Languages / C#

Deep Binding

Rate me:
Please Sign up or sign in to vote.
4.30/5 (14 votes)
2 Jul 2005CPOL2 min read 70.4K   1K   25  
Binding Complex objects to Windows Forms controls
using System;
using System.ComponentModel ;
using System.Collections ;
using System.Reflection ;
namespace DeepBinding
{
	/// <summary>
	/// Summary description for BindableObject.
	/// </summary>
	public class BindableObject: ICustomTypeDescriptor
	{
		public BindableObject()
		{
			//
			// TODO: Add constructor logic here
			//
		}
		#region ICustomTypeDescriptor Members

		System.ComponentModel.AttributeCollection ICustomTypeDescriptor.GetAttributes()
		{
			return TypeDescriptor.GetAttributes(this, true);
		}
		string ICustomTypeDescriptor.GetClassName()
		{
			return TypeDescriptor.GetClassName(this, true);
		}
		string ICustomTypeDescriptor.GetComponentName()
		{
			return TypeDescriptor.GetComponentName (this, true);
		}
		TypeConverter ICustomTypeDescriptor.GetConverter ()
		{
			return TypeDescriptor.GetConverter(this, true);
		}
		EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
		{
			return TypeDescriptor.GetDefaultEvent (this, true);
		}
		PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
		{
			return TypeDescriptor.GetDefaultProperty(this, true);
		}
		object ICustomTypeDescriptor.GetEditor(Type editorBaseType) 
		{
			return TypeDescriptor.GetEditor(this, editorBaseType , true);
		}
		EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
		{
			return TypeDescriptor.GetEvents(this, true);
		}
		EventDescriptorCollection ICustomTypeDescriptor.GetEvents(System.Attribute[] atttributes)
		{
			return TypeDescriptor.GetEvents(this, atttributes , true);
		}
		object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
		{
			return this;
		}
		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
		{
			//return TypeDescriptor.GetProperties(this, true);
			return new PropertyDescriptorCollection(GetCustomProperties());
		}
		PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(System.Attribute[] attributes)
		{
			try
			{
				return new PropertyDescriptorCollection(GetCustomProperties());
			}
			catch(System.Exception ex)
			{
				throw ex;
			}
		}
		#endregion
		#region Object Description
		private Type _TypeofObject;
		private Type TypeOfObject
		{
			get
			{
				if (_TypeofObject ==null)
					_TypeofObject = this.GetType();
				return _TypeofObject;
			}
		}
		internal PropertyInfo [] ObjectPropertyInfo
		{
			get
			{
				PropertyInfo [] Pis = null;
				if (ObjectProperties.Contains(this.TypeOfObject.ToString()))
				{
					Pis= (PropertyInfo[]) ObjectProperties[this.TypeOfObject.ToString()];
				}
				else
				{
					Pis =TypeOfObject.GetProperties(BindingFlags.Public | 
						BindingFlags.Instance | BindingFlags.SetProperty);
					ObjectProperties.Add(TypeOfObject.ToString(), Pis);
				}
				if (Pis ==null)
				{
					throw new Exception("Error occured when getting object properties");
				}
				return Pis;
			}
		}

		//Implementing cache to increase performance
		internal static System.Collections.Hashtable POCustomProperties = new System.Collections.Hashtable();
		internal static System.Collections.Hashtable ObjectProperties = new Hashtable();


		public CustomPropertyDescriptor[] GetCustomProperties()
		{
			try
			{
				CustomPropertyDescriptor[] _Properties =null;
				//getting object structure from cache
				if (POCustomProperties.Contains(this.TypeOfObject.ToString() + "Properties"))
				{
					return (CustomPropertyDescriptor[]) POCustomProperties[this.TypeOfObject.ToString() + "Properties"];
				}
				System.Collections.ArrayList Al = new System.Collections.ArrayList();
				CustomPropertyDescriptor cpd;
				foreach(PropertyInfo P in this.ObjectPropertyInfo)
				{
					//looking for properties that inherits from baseobject
					if ( InheritsFrom(P.PropertyType, typeof(BindableObject) ))
					{
						cpd = new CustomPropertyDescriptor(P.Name, P);
						Al.Add(cpd);
						Object PropValue = P.GetValue(this, null);
						if (PropValue !=null)
						{
							CustomPropertyDescriptor[] SubItemProps =((BindableObject) PropValue).GetCustomProperties();
							for (int i = 0; i <= SubItemProps.GetUpperBound(0) ;i++)
							{
								CustomPropertyDescriptor ModifiedProp = new CustomPropertyDescriptor(P.Name  + "." + SubItemProps[i].Name, SubItemProps[i].Prop);
								Al.Add(ModifiedProp);
								//Console.WriteLine("Prop : " + ModifiedProp.Name );
							}
						}
					}
					else
					{
						System.ComponentModel.AttributeCollection attributes = TypeDescriptor.GetProperties(this,true)[P.Name].Attributes;

						if(attributes[typeof(BrowsableAttribute)].Equals(BrowsableAttribute.Yes))
						{
							cpd = new CustomPropertyDescriptor(P.Name, P);
							Al.Add(cpd);
						}
					}
				}
				
				_Properties = new CustomPropertyDescriptor[Al.Count ];
				for(int i = 0; i< Al.Count ; i++)
				{
					_Properties[i] = (CustomPropertyDescriptor) Al[i];
				}
				POCustomProperties.Add(this.TypeOfObject.ToString() + "Properties", _Properties);
				return _Properties;
				
			}
			catch(System.Exception ex)
			{
				throw ex;
			}
		}
		public bool InheritsFrom(Type value, Type BaseType)
		{
			Type BaseClassType = value;
			while ( (BaseClassType !=null & BaseClassType != BaseType) ==true) 
			{
				BaseClassType = BaseClassType.BaseType ;
			}
			if (BaseType== BaseClassType)
				return true;
			else
				return false;
		}
		#endregion		
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
France France
MCSD Asp.Net certified developer

Comments and Discussions