/// <summary> /// Examines the type of the bound object and initializes all neccessary structures /// that are needed before binding can start. This methods to be called once for /// each type passed as <paramref name="target"/> (not for each object of that type). /// </summary> /// <param name="target">bound object</param> /// <param name="sourceType">Type of binding (model/view helper).</param> private void PrepareBindingTo(IBindable target, EBindingSourceType sourceType) { if (sourceType == EBindingSourceType.Model) { PropertyInfo modelProperty = FindFieldByAttribute(Type, typeof(ModelElementAttribute)); ModelElementType = modelProperty.GetValue(target, null).GetType(); if (ModelElementType == null) { throw new InvalidOperationException(string.Format("Model property for type {0} is not assigned or the property is not marked with ModelElementAttribute", Type)); } if (!initializationInProgress) { Debug.WriteLine("Model binding for type " + target.GetType().Name + " with model type " + ModelElementType.Name); } ModelSourceGetter = DynamicMethodCompiler.CreateGetHandler(ModelElementType, modelProperty); CreateBindingFunctions(sourceType, ModelElementType); } if (sourceType == EBindingSourceType.View) { PropertyInfo viewHelperProperty = FindFieldByAttribute(Type, typeof(ViewHelperElementAttribute)); ViewHelperType = viewHelperProperty.GetValue(target, null).GetType(); if (ViewHelperType == null) { throw new InvalidOperationException(string.Format("ViewHelper for type {0} is not assigned or the property is not marked with ViewHelperElementAttribute", Type)); } if (!initializationInProgress) { Debug.WriteLine("View binding for type " + target.GetType().Name + " with view type " + ViewHelperType.Name); } ViewSourceGetter = DynamicMethodCompiler.CreateGetHandler(ViewHelperType, viewHelperProperty); CreateBindingFunctions(sourceType, ViewHelperType); } }
/// <summary> /// Starts bindings to properties of model element /// or view helper of the object <paramref name="target"/>. /// </summary> /// <param name="target">The bound object</param> /// <param name="sourceType">Type of binding (model/view helper).</param> /// <seealso cref="ModelElementAttribute"/> /// <seealso cref="ViewHelperElementAttribute"/> public void StartBindings(IBindable target, EBindingSourceType sourceType) { if (initializationInProgress) { lock (initializationLock) { } } bool isReady = false; if (sourceType == EBindingSourceType.Model && ModelSourceGetter != null) { isReady = true; } if (sourceType == EBindingSourceType.View && ViewSourceGetter != null) { isReady = true; } if (!isReady) { PrepareBindingTo(target, sourceType); } if (!initializationInProgress) { BindingCollection getterCollection = (sourceType == EBindingSourceType.Model) ? ModelGetterCollection : ViewGetterCollection; foreach (string key in getterCollection.Keys) { UpdateValue(target, key, sourceType); } } }
/// <summary> /// Creates the binding functions (fills <see cref="ViewSetterCollection"/> and /// <see cref="ViewGetterCollection"/> or <see cref="ModelSetterCollection"/> and /// <see cref="ModelGetterCollection"/> with correct handlers). The handlers are /// dynamically compiled. /// </summary> /// <param name="sourceType">Type of the source to bound to</param> /// <param name="boundType">Type of the bound object</param> private void CreateBindingFunctions(EBindingSourceType sourceType, Type boundType) { if (sourceType == EBindingSourceType.View) { foreach (ViewHelperPropertyMappingAttribute attribute in ViewMappingDeclarations) { if (!initializationInProgress) { Debug.WriteLine("View binding: " + attribute.SourcePropertyName + " -> " + attribute.declaringProperty.Name); } PropertyInfo sourceProp = boundType.GetProperty(attribute.SourcePropertyName); ViewGetterCollection[sourceProp.Name] = DynamicMethodCompiler.CreateGetHandler(boundType, sourceProp); ViewSetterCollection[sourceProp.Name] = DynamicMethodCompiler.CreateSetHandler(Type, attribute.declaringProperty); } } if (sourceType == EBindingSourceType.Model) { foreach (ModelPropertyMappingAttribute attribute in ModelMappingDeclarations) { if (!initializationInProgress) { Debug.WriteLine("Model binding: " + attribute.SourcePropertyName + " -> " + attribute.declaringProperty.Name); } PropertyInfo sourceProp = boundType.GetProperty(attribute.SourcePropertyName); ModelGetterCollection[sourceProp.Name] = DynamicMethodCompiler.CreateGetHandler(boundType, sourceProp); ModelSetterCollection[sourceProp.Name] = DynamicMethodCompiler.CreateSetHandler(Type, attribute.declaringProperty); } } }
/// <summary> /// Updates the bound value of the bound property of <paramref name="boundObject"/> /// when value of <paramref name="property"/> is changed in the binding source. /// </summary> /// <param name="boundObject">The bound object</param> /// <param name="property">The property that changed in model or viewhelper </param> /// <param name="sourceType">Type of binding (model/view helper).</param> private void UpdateValue(IBindable boundObject, string property, EBindingSourceType sourceType) { if (sourceType == EBindingSourceType.Model && ModelGetterCollection.ContainsKey(property)) { object value = ((GetHandler)ModelGetterCollection[property])(ModelSourceGetter(boundObject)); ((SetHandler)ModelSetterCollection[property])(boundObject, value); } if (sourceType == EBindingSourceType.View && ViewGetterCollection.ContainsKey(property)) { object value = ((GetHandler)ViewGetterCollection[property])(ViewSourceGetter(boundObject)); ((SetHandler)ViewSetterCollection[property])(boundObject, value); } }
/// <summary> /// Suspends the binding for the object <paramref name="target"/>. /// </summary> /// <param name="target">The bound object</param> /// <param name="sourceType">Type of binding (model/view helper).</param> public void CloseBindings(IBindable target, EBindingSourceType sourceType) { if (sourceType == EBindingSourceType.View) { if (ViewUpdaters.ContainsKey(target)) { ((INotifyPropertyChanged)ViewSourceGetter(target)).PropertyChanged -= (PropertyChangedEventHandler)ViewUpdaters[target]; ViewUpdaters.Remove(target); } } else { if (ModelUpdaters.ContainsKey(target)) { ((INotifyPropertyChanged)ModelSourceGetter(target)).PropertyChanged -= (PropertyChangedEventHandler)ModelUpdaters[target]; ModelUpdaters.Remove(target); } } }