 				
 				providerBindingNames.push(bindingName);
 				_bindingNames.push(bindingName);
+				
+				getPropertyChangedSignal(bindingName).execute(this, bindingName, attribute);
 			}
 			
 			_providerToBindingNames[provider] = providerBindingNames;
 		}
 		
-		public function remove(dataProvider : IDataProvider) : void
-		{
-			var bindingNames : Vector.<String> = _providerToBindingNames[dataProvider];
+		public function remove(provider : IDataProvider) : void
+		{
+			var bindingNames : Vector.<String> = _providerToBindingNames[provider];
 			
 			if (bindingNames == null)
 				throw new ArgumentError('No such provider was binded');
 			
-			dataProvider.changed.remove(onProviderChange);
-			
-			for (var bindingName : String in bindingNames)
-			{
-				_bindingNames.splice(_bindingNames.indexOf(bindingName), 1);
+			for each (var bindingName : String in bindingNames)
+			{
+				var indexOf : int = _bindingNames.indexOf(bindingName);
+				
+				_bindingNames.splice(indexOf, 1);
 				
 				if (_bindingNameToValue[bindingName] is IDataProvider)
 					IDataProvider(_bindingNameToValue[bindingName]).changed.remove(onProviderAttributeChange);
 				
 				delete _bindingNameToValue[bindingName];
-				
 			}
 			
 			var attributesToDelete : Vector.<Object> = new Vector.<Object>();

			var attrNames		: Vector.<String>			= _attributeToProvidersAttrNames[source];
			var numProviders	: uint						= providers.length;
			
			// can do faster than that :p
			for (var providerId : uint = 0; providerId < numProviders; ++providerId)
				onProviderChange(providers[providerId], attrNames[providerId]);
		}
	}
}
		/**
		 * A provider attribute has changed, and the provider tells us.
		 * For example, camera.fov has changed, the camera dispatches a 'changed' signal with 'fov' as attributeName.
		 * 
		 * It could also be that camera.localToWorld has been replaced by another matrix instance.
		 */
		private function onProviderChange(source : IDataProvider, attributeName : String) : void
		{
			if (attributeName == null)
			{
				throw new Error('DataProviders must change one property at a time.');
			}
			else if (attributeName == 'dataDescriptor')
			{
				remove(source);
				add(source);
			}
			else
			{
				var bindingName : String		= source.dataDescriptor[attributeName];
				var oldDpValue	: IDataProvider	= _bindingNameToValue[bindingName] as IDataProvider;
				var newValue	: Object		= source[attributeName];
				var newDpValue	: IDataProvider	= newValue as IDataProvider;
				
				// we are replacing a data provider. We must remove listeners and related mapping keys
				if (oldDpValue != null)
				{
					oldDpValue.changed.remove(onProviderAttributeChange);
					
					var providers	: Vector.<IDataProvider>	= _attributeToProviders[oldDpValue];
					var attrNames	: Vector.<String>			= _attributeToProvidersAttrNames[oldDpValue];
					
					if (providers.length == 1)
					{
						delete _attributeToProviders[oldDpValue];
						delete _attributeToProvidersAttrNames[oldDpValue];
					}
					else
					{
						var index : uint = providers.indexOf(source);
						providers.splice(index, 1);
						attrNames.splice(index, 1);
					}
				}
				
				// the new value for this key is a dataprovider, we must listen changes.
				if (newDpValue != null)
				{
					newDpValue.changed.add(onProviderAttributeChange);
					
					if (!_attributeToProviders[newDpValue])
						_attributeToProviders[newDpValue] = new <IDataProvider>[];
					
					if (!_attributeToProvidersAttrNames[newDpValue])
						_attributeToProvidersAttrNames[newDpValue] = new <String>[];
					
					_attributeToProviders[newDpValue].push(source);
					_attributeToProvidersAttrNames[newDpValue].push(attributeName);
				}
				
				_bindingNameToValue[bindingName] = newValue;
				
				getPropertyChangedSignal(bindingName).execute(this, bindingName, newValue);
			}
