=> target.DataContextChanged -= DatacontextTarget_DataContextChanged;      // free up event handlers.

        /// <summary>
        /// Called whenever the datacontext of one of the inner source binding changed.
        /// </summary>
        /// <param name="sender">A framework element for which the property changed.</param>
        /// <param name="e">Information about the datacontext changed event.</param>
        private void DatacontextTarget_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            if (TargetObject == sender && TargetProperty != null)
            {
                ToggleBinding(BindingHelpers.GetBindingSource(innerBinding, TargetObject, out bool _, out bool _));
            }
            else if (sender is FrameworkElement casted)
            {
                casted.DataContextChanged -= DatacontextTarget_DataContextChanged;
            }
        }
        protected override void OnTargetLoaded(FrameworkElement target) => Initialize(); // retry class initialization at loaded.

        /// <summary>
        /// Prepares this class to filter data based on resolved (or unresolved source).
        /// </summary>
        private void Initialize()
        {
            if (initialized)
            {
                return;
            }

            // Find source value here if not provided:
            var source = BindingHelpers.GetBindingSource(innerBinding, TargetObject, out bool resolved, out bool _);

            if (resolved)
            {
                Initialize(source);
            }
        }
示例#3
0
 /// <summary>
 /// Called whenever the datacontext of target object changed.
 /// </summary>
 /// <param name="sender">A framework element for which the property changed.</param>
 /// <param name="e">Information about the datacontext changed event.</param>
 private void DatacontextTarget_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
 {
     if (TargetObject == sender && TargetProperty != null)
     {
         if (bindingWatcher != null)
         {
             bindingWatcherDescriptor.RemoveValueChanged(bindingWatcher, BindingWatcher_SourcePropertyChanged);
             bindingWatcher.Dispose();
         }
         bindingWatcher           = new DependencyPropertyWatcher <object>(BindingHelpers.GetBindingSource(InnerBinding, TargetObject, out bool _, out bool _), InnerBinding.Path);
         bindingWatcherDescriptor = bindingWatcherDescriptor = DependencyPropertyDescriptor.FromProperty(DependencyPropertyWatcher <object> .ValueProperty, typeof(DependencyPropertyWatcher <object>));
         bindingWatcherDescriptor.AddValueChanged(bindingWatcher, BindingWatcher_SourcePropertyChanged);
     }
     else if (sender is FrameworkElement casted)
     {
         casted.DataContextChanged -= DatacontextTarget_DataContextChanged;
     }
 }
        /// <summary>
        /// Resolves path binding and prepares the inner custom binding with resolved path value.
        /// </summary>
        /// <param name="serviceProvider">Service provider given by the framework.</param>
        /// <returns>True if successfully prepared path binding, false if cannot resolve its value.</returns>
        private bool ResolveBoundPathBinding(IServiceProvider serviceProvider = null)
        {
            if (PathValueBinding == null)
            {
                return(false);
            }

            // If source is not already resolved:
            if (boundPathSource == null)
            {
                // Try to get the source of value for the path value binding using base mechanisms:
                boundPathSource = serviceProvider != null?BindingHelpers.GetBindingSource(PathValueBinding, serviceProvider, out bool source_is_resolved, out bool source_is_datacontext)
                                      : BindingHelpers.GetBindingSource(PathValueBinding, TargetObject, out source_is_resolved, out source_is_datacontext);

                if (!source_is_resolved || boundPathSource == null)
                {
                    return(false);
                }

                // If source is datacontext then track it for future changes:
                if (source_is_datacontext)
                {
                    (TargetObject as FrameworkElement).DataContextChanged += TargetObject_DataContextChanged;
                }
            }

            // Try to resolve path binding value on the source:
            var value = BindingHelpers.ResolvePathValue(boundPathSource, PathValueBinding.Path);

            // If not given a proper property path format:
            if (!(value is string) && !(value is PropertyPath))
            {
                StopTrackingPathBindingUpdates(); // as we did not resolved binding, stop tracking changes on current bind if any.
                return(false);
            }

            // Update bound path binding by getting a copy of the precedent value:
            if (!providing_value)
            {
                boundPathBinding = boundPathBinding?.Clone();
                if (boundPathBinding == null)
                {
                    return(false);
                }
            }

            // Build new inner binding path based on resolved value + OverridePath property:
            if (value is string as_string)
            {
                if (!OverridePath && Path != null)
                {
                    boundPathBinding.Path = new PropertyPath(Path.Path + "." + as_string);  // TODO: path parameters?
                }
                else
                {
                    boundPathBinding.Path = new PropertyPath(as_string);
                }
            }
            else if (value is PropertyPath asPropertyPath)
            {
                if (!OverridePath && Path != null)
                {
                    boundPathBinding.Path = new PropertyPath(Path.Path + "." + asPropertyPath.Path, asPropertyPath.PathParameters);
                }
                else
                {
                    boundPathBinding.Path = asPropertyPath;
                }
            }

            // As we resolved binding, track any further changes:
            StartTrackingPathBindingUpdates();

            return(true);
        }