//////////////////////////////////////////////////////////////////////////////////////////////////// // NoesisGUI - http://www.noesisengine.com // Copyright (c) 2013 Noesis Technologies S.L. All Rights Reserved. //////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef __GUI_BINDINGEXPRESSION_H__ #define __GUI_BINDINGEXPRESSION_H__ #include #include #include #include #include #include #include namespace Noesis { NS_INTERFACE IValueConverter; NS_INTERFACE INameScope; class DependencyObject; class DependencyProperty; class FrameworkElement; class CollectionView; struct PropertyChangedEventArgs; struct NotifyDictionaryChangedEventArgs; struct NotifyCollectionChangedEventArgs; struct DependencyPropertyChangedEventArgs; struct RoutedEventArgs; struct EventArgs; struct AncestorNameScopeChangedArgs; struct NameScopeChangedArgs; NS_WARNING_PUSH NS_MSVC_WARNING_DISABLE(4251 4275) //////////////////////////////////////////////////////////////////////////////////////////////////// /// Contains information about a single instance of a Binding. /// /// https://msdn.microsoft.com/en-us/library/system.windows.data.bindingexpression.aspx //////////////////////////////////////////////////////////////////////////////////////////////////// class NS_GUI_CORE_API BindingExpression final: public BaseBindingExpression { public: ~BindingExpression(); NS_DECLARE_POOL_ALLOCATOR /// Binding from which this expression was created /// \prop Binding* GetParentBinding() const; /// Gets the binding source object for this BindingExpression /// \prop BaseComponent* GetResolvedSource() const; /// From BaseBindingExpression //@{ void UpdateTarget() const override; void UpdateSource() const override; //@} /// From Expression //@{ Ptr Evaluate() const override; Ptr Reapply(DependencyObject* targetObject, const DependencyProperty* targetProperty) const override; BeforeSetAction BeforeSet(DependencyObject* obj, const DependencyProperty* prop, const void* value, bool valueChanged) override; void AfterSet(DependencyObject* obj, const DependencyProperty* prop, const void* value, bool valueChanged) override; //@} private: friend class Binding; BindingExpression(BaseBinding* binding, DependencyObject* targetObject, const DependencyProperty* targetProperty); bool IsAttached() const; void Register(); void Unregister(); void RegisterTarget(FrameworkElement* target, Binding* binding); void UnregisterTarget(FrameworkElement* target); void RegisterScope(); void UnregisterScope(); void Initialize(); void Shutdown(); void AddPathElement(const PathElement& element, void* context); void RegisterSource(); void UnregisterSource(); struct WeakPathElement; uint32_t GetRegisteredFlags(uint32_t end, const WeakPathElement& element) const; void RegisterNotification(const WeakPathElement& element, uint32_t registeredFlags); void UnregisterNotification(const WeakPathElement& element, uint32_t registeredFlags); bool IsSelf() const; bool IsSourceReadOnly(Symbol& propOwner, Symbol& propName) const; Ptr GetValue(const WeakPathElement& element, const Type*& valueType) const; // Checks if a converter is needed, creating one when required bool CheckConverter(const Type* sourceType, BaseComponent* sourceVal, const Type* targetType, BaseComponent* targetVal) const; void UpdateSourceInternal(const void* value) const; void TransferSourceValue(const void* value) const; Ptr GetSourceValue() const; void ResetTargetValue() const; void InvalidateTarget() const; void InvalidateSource(bool invalidateTargetProperty = true); // Source change notification //@{ void OnDataContextParentChanged(FrameworkElement* oldParent); void OnDataContextChanged(BaseComponent* sender, const DependencyPropertyChangedEventArgs& args); void OnAncestorChanged(FrameworkElement* ancestor); void OnAncestorNameScopeChanged(FrameworkElement* sender, const AncestorNameScopeChangedArgs& args); void OnSourceNameScopeChanged(INameScope* sender, const NameScopeChangedArgs& args); //@} // Property change notifications //@{ void OnDependencyPropertyChanged(BaseComponent* sender, const DependencyPropertyChangedEventArgs& args); void OnNotifyPropertyChanged(BaseComponent* sender, const PropertyChangedEventArgs& e); void OnCollectionChanged(BaseComponent* sender, const NotifyCollectionChangedEventArgs& args); void OnCollectionReset(BaseComponent* sender, const NotifyCollectionChangedEventArgs& args); void OnDictionaryChanged(BaseComponent* sender, const NotifyDictionaryChangedEventArgs& args); void OnDictionaryReset(BaseComponent* sender, const NotifyDictionaryChangedEventArgs& args); void OnCurrentChanged(BaseComponent* sender, const EventArgs& args); //@} // Event notification //@{ void OnTargetLostFocus(BaseComponent*, const RoutedEventArgs& args); void OnTargetLoaded(BaseComponent*, const RoutedEventArgs&); void OnTargetUnloaded(BaseComponent*, const RoutedEventArgs&); void OnTargetObjectDestroyed(DependencyObject* object); void OnTargetDestroyed(DependencyObject* object); void OnSourceDestroyed(DependencyObject* object); //@} bool IsTargetAlive() const; private: BaseComponent* mSource; FrameworkElement* mTargetElement; INameScope* mNameScope; struct WeakPathElement { BaseComponent* source; CollectionView* collection; const TypeProperty* property; const DependencyProperty* dp; const char* key; int index; }; // List of objects to access final source property Vector mPaths; // Effective binding mode (never set to Default because proper value is retrieved from metadata) BindingMode mEffectiveBindingMode; // Value converter is used when source and target property types are different, or when set by // the user in the Converter field of the Binding class mutable Ptr mEffectiveConverter; // The effective UpdateSourceTrigger value to use UpdateSourceTrigger mEffectiveUpdateSourceTrigger; // The delay timer identifier int mDelayTimer; union { mutable struct { bool fullReevaluationNeeded : 1; bool pathPartiallySolved : 1; bool sourceRegistered : 1; bool targetDestroyRegistered : 1; bool targetLostFocusRegistered : 1; bool targetAncestorChangedRegistered : 1; bool targetDataContextParentChangedRegistered : 1; bool targetDataContextChangedRegistered : 1; bool targetAncestorNameScopeChangedRegistered : 1; bool targetLoadedRegistered : 1; bool targetValueReset : 1; bool propertyChangeRegistered : 1; bool collectionResetRegistered : 1; bool dictionaryResetRegistered : 1; bool updatingSource : 1; bool updatingTarget : 1; bool transferingSourceValue : 1; bool doNothing : 1; bool checkConverter : 1; bool oneTimeEvaluated : 1; } mFlags; // To quickly set all flags to 0 uint32_t mAllFlags; }; NS_DECLARE_REFLECTION(BindingExpression, BaseBindingExpression) }; NS_WARNING_POP } #endif