Пример #1
0
 /// <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 (sender is FrameworkElement casted)
     {
         // Only if extension is still alive:
         if (IsExtensionValid)
         {
             // Loop through every bindings set on datacontext that we registered,
             // and hook to collection change event for the new datacontext value:
             foreach (var binding in DataContextBindings.Keys)
             {
                 if (DataContextBindings[binding] == casted)
                 {
                     if (BindingHelpers.ResolvePathValue(casted.DataContext, binding.Path) is INotifyCollectionChanged collection)
                     {
                         CollectionChangedEventManager.AddListener(collection, this);
                     }
                 }
             }
         }
         else
         {
             casted.DataContextChanged -= DatacontextTarget_DataContextChanged;
         }
     }
 }
Пример #2
0
        /// <summary>
        /// Gets the current value of the binding targeted property.
        /// </summary>
        /// <param name="binding">The binding description indicating where to find the source and the value.</param>
        /// <param name="target">A target object where the source might be found.</param>
        /// <returns>The property value that is described by the binding.</returns>
        protected object getBindingSourcePropertyValue(Binding binding, FrameworkElement target)
        {
            var sourceElement = getBindingSource(binding, target);

            // Process source element to retrieve target property:
            if (sourceElement != null)
            {
                return(BindingHelpers.ResolvePathValue(sourceElement, binding.Path));
            }
            else
            {
                return(null);
            }
        }
        /// <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);
        }