#pragma warning restore CA1000 // Do not declare static members on generic types #endregion #region Internal Static Methods internal static object ProvideValue( DependencyObject target, DependencyProperty property, object defaultValue, BindingBase xamlBinding) { if (target == null || property == null) { return(null); } object outputValue = defaultValue; if (outputValue == null || string.IsNullOrEmpty(outputValue.ToString())) { throw new InvalidOperationException($@"No default value provided for property ""{target}.{property.Name}"""); } if (!outputValue.GetType().IsSerializable) { throw new InvalidOperationException($@"Default value provided for property ""{target}.{property.Name}"" is not serializable"); } FrameworkElement visualAnchor = AbstractPropertyState <TState, TElement, TProperty> .GetVisualAnchor(target); if (!(target is FrameworkElement element) || visualAnchor != null) { element = visualAnchor; } var defaultString = outputValue as string; if (!string.IsNullOrEmpty(defaultString)) { outputValue = AbstractPropertyState <TState, TElement, TProperty> .ConvertFromString(target.GetType(), property, defaultString); } var propertyMultiValueConverter = new PropertyMultiValueConverter() { Target = element, Property = property, }; void handler(object s, RoutedEventArgs e) { if (element != null) { element.Loaded -= handler; } if (xamlBinding != null && !IsPropertyPersisted(target, property)) { // Normally the persisted state is the initial value used // for an element property when the UI is rendered, but if // no value is persisted (and a data bound property is present) // then use the data bound value. propertyMultiValueConverter.PropertyValuePreference = PropertyValuePreference.DataBound; } if (!HasPropertyValue(target, property)) { object value = AddPropertyValue(target, property, outputValue); if (value == null) { throw new InvalidOperationException($@"The element ""{target}"" has no unique identifier for property persistence"); } } var multiBinding = new MultiBinding() { Converter = propertyMultiValueConverter, Mode = BindingMode.TwoWay, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged, }; // Add a new binding between the element property and the // persisted state. multiBinding.Bindings.Add(CreateStateBinding(target, property)); if (xamlBinding != null) { // If the element property was previously data bound in XAML // then add that binding to the multibinding collection. multiBinding.Bindings.Add(xamlBinding); } BindingOperations.SetBinding(target, property, multiBinding); if (element.IsLoaded) { propertyMultiValueConverter.PropertyValuePreference = PropertyValuePreference.DataBound; } } // Windows are already loaded when the application starts // so need to invoke their loaded handlers manually. if (target is Window) { handler(null, null); } // Keep track of the loaded handlers in case they need to // activated manually later. AddPropertyLoadedHandler(target, property, handler); if (element != null) { element.Loaded += handler; } if (HasPropertyValue(target, property)) { return(GetPropertyValue(target, property)); } return(outputValue); }
internal static string GetUidWithNamespace(DependencyObject element) { return($@"{AbstractPropertyState<TState, TElement, TProperty>.GetNamespace(element)}{AbstractPropertyState<TState, TElement, TProperty>.GetUid(element)}"); }