public override object ProvideValue(IServiceProvider serviceProvider) { if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } // Other useful services: // - IDestinationTypeProvider // - IRootObjectProvider if (!(serviceProvider.GetService(typeof(IProvideValueTarget)) is IProvideValueTarget service)) { return(null); } if (service.TargetObject is DependencyObject depObj) { if (Binding != null || _bindings?.Count > 0) { if (false == (service.TargetProperty is DependencyProperty)) { // The what bindings are implemented in WPF provides no way to obtain the value // produced by the binging. The only way is to update the property directly. Therefore, // the extension cannot support bindings on non-dependency properties (same as WPF). throw new NotSupportedException("Bindings are supported only on dependency properties."); } } LocalizedProperty localizedProperty; if (service.TargetProperty is DependencyProperty depProperty) { localizedProperty = new LocalizedDepProperty(depProperty); } else if (service.TargetProperty is PropertyInfo propertyInfo) { localizedProperty = new LocalizedNonDepProperty(propertyInfo); } else { throw new NotSupportedException($"The default property provider supports only dependency and non-dependency properties of dependency objects. Properties of type {service.TargetProperty.GetType()} are not supported."); } var localizedValue = new LocalizedValue(depObj, localizedProperty) { Key = this.Key, StringFormat = this.StringFormat, Callback = this.Callback, CallbackParameter = this.CallbackParameter, Binding = this.Binding, Bindings = this._bindings, Converter = this.Converter, ConverterParameter = this.ConverterParameter, }; LocalizationManager.Add(localizedValue); if (localizedValue.IsInDesignMode) { // At design time VS designer does not set the parent of any control // before its properties are set. For this reason the correct values // of inherited attached properties cannot be obtained. // Therefore, to display the correct localized value it must be updated // later after the parent of the control has been set. depObj.Dispatcher.BeginInvoke( DispatcherPriority.ApplicationIdle, new SendOrPostCallback(x => ((LocalizedValue)x).UpdateValue()), localizedValue ); return(localizedProperty.DefaultValue); } else { return(localizedValue.GetValue(depObj)); } } else if (service.TargetObject is Setter) { /* // DEPRECATED * if (Binding != null || _bindings?.Count > 0) * { * throw new NotSupportedException("Bindings are not supported in style setters."); * } */ var rootObjectProvider = (IRootObjectProvider)serviceProvider.GetService(typeof(IRootObjectProvider)); Debug.Assert(rootObjectProvider != null); var rootObject = rootObjectProvider.RootObject as DependencyObject; Debug.Assert(rootObject != null); #if DEPRECATED // Unfortunately "GetDestinationType" throws NullReferenceException therefore, this approach is not applicable for retrieving the property's type var destinationTypeProvider = (IDestinationTypeProvider)serviceProvider.GetService(typeof(IDestinationTypeProvider)); Debug.Assert(destinationTypeProvider != null); var targetPropertyType = destinationTypeProvider.GetDestinationType(); var localizedValue = new SetterLocalizedValue(rootObject, targetPropertyType) { Key = this.Key, Callback = this.Callback, CallbackParameter = this.CallbackParameter, Converter = this.Converter, ConverterParameter = this.ConverterParameter, }; #endif var localizedValue = new LocalizedSetterValue(rootObject) { Key = this.Key, StringFormat = this.StringFormat, Callback = this.Callback, CallbackParameter = this.CallbackParameter, Binding = this.Binding, Bindings = this._bindings, Converter = this.Converter, ConverterParameter = this.ConverterParameter, }; BindingBase finalBinding; if (Binding != null || _bindings?.Count > 0) { var binding = new MultiBinding() { Mode = BindingMode.OneWay, Converter = localizedValue, }; if (Binding != null) { binding.Bindings.Add(Binding); if (_bindings?.Count > 0) { foreach (var item in Bindings) { binding.Bindings.Add(item); } } } finalBinding = binding; } else { finalBinding = new Binding(nameof(LocalizedSetterValue.Value)) { Source = localizedValue, Mode = BindingMode.OneWay, Converter = localizedValue, }; } LocalizationManager.Add(localizedValue); return(finalBinding); } else if (service.TargetProperty is DependencyProperty || service.TargetProperty is PropertyInfo) { // The extension is used in a template and will be evaluated once the template is instantiated return(this); } else { throw new NotSupportedException($"The localization extension can be used only with {nameof(DependencyObject)}s."); } }