 		/**
 		 * 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 == 'dataDescriptor')
-			{
-				throw new Error('implement');
-			}
-			else if (attributeName == null)
-			{
-				throw new Error('implement');
+			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	: Object		= _bindingNameToValue[bindingName];
-				var newDPValue	: IDataProvider	= source[attributeName] as IDataProvider;
-				
-				if ()
-				{
-					
-					
-					_bindingNameToValue[bindingName] = newValue;
-					
-				}
-				
+				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);
 			}

			{
				delete _attributeToProviders[attributeToDelete];
				delete _attributeToProvidersAttrNames[attributeToDelete];
			}
		}
		

			var attrNames		: Vector.<String>			= _attributeToProvidersAttrNames[source];
			var numProviders	: uint						= providers.length;
			
			for (var providerId : uint = 0; providerId < numProviders; ++providerId)
			{
				var provider	: IDataProvider	= providers[providerId];
				var attrName	: String		= attrNames[providerId];
				var bindingName : String		= provider.dataDescriptor[attrName];
				
				getPropertyChangedSignal(bindingName).execute(this, bindingName, source);
			}
		}
	}
}