/// <summary> /// Gets the binding source object of a binding. /// </summary> /// <param name="binding">The binding that indicates the source.</param> /// <param name="serviceProvider">Service provider provided by the framework.</param> /// <returns>The source object that is described by the binding.</returns> protected object getBindingSource(Binding binding, IServiceProvider serviceProvider) { if (binding == null) { return(null); } // Optionaly get the target object: var pvt = serviceProvider?.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget; var targetObject = pvt?.TargetObject != null ? pvt.TargetObject as DependencyObject : null; // -- Case where source is explicitely provided: -- if (binding.Source != null) { // Get target object as FE if provided: if (targetObject is FrameworkElement targetAsFE) { // And if the binding source is the datacontext of the target object, then add // the object the to list of datacontexts to be followed: if (targetAsFE.IsLoaded && targetAsFE.DataContext == binding.Source) { if (!DataContextBindings.ContainsKey(binding)) { DataContextBindings.Add(binding, targetAsFE); } return(binding.Source); } // Else we cannot know now ,so report assessment when target will be loaded by setting // the current binding as 'unresolved': else if (!targetAsFE.IsLoaded) { UnresolvedBindings.Add(binding, targetAsFE); } } else { return(binding.Source); } } // -- Case where element name is provided, seek source in xaml: -- else if (!string.IsNullOrWhiteSpace(binding.ElementName) && serviceProvider != null) { return(BindingHelpers.GetSourceFromElementName(binding.ElementName, serviceProvider)); } // -- All other case where we have a target to provide: -- else if (targetObject != null) { return(getBindingSource(binding, targetObject)); // call the other method without service provider. } return(null); }