// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. /***************************************************************************\ * * Class for converting a given value (for Setter/Trigger/Condition) to and from a string * \***************************************************************************/ using System.ComponentModel; // for TypeConverter using System.Globalization; // for CultureInfo using System.Xaml; using System.IO; namespace System.Windows.Markup { /// <summary> /// Class for converting a given DependencyProperty to and from a string /// </summary> public sealed class SetterTriggerConditionValueConverter : TypeConverter { #region Public Methods /// <summary> /// CanConvertFrom() /// </summary> /// <param name="context">ITypeDescriptorContext</param> /// <param name="sourceType">type to convert from</param> /// <returns>true if the given type can be converted, false otherwise</returns> public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { // We can only convert from a string and that too only if we have all the contextual information // Note: Sometimes even the serializer calls CanConvertFrom in order // to determine if it is a valid converter to use for serialization. if (sourceType == typeof(string) || sourceType == typeof(byte[])) { return true; } return false; } /// <summary> /// TypeConverter method override. /// </summary> /// <param name="context">ITypeDescriptorContext</param> /// <param name="destinationType">Type to convert to</param> /// <returns>true if conversion is possible</returns> public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { return false; } /// <summary> /// ConvertFrom() -TypeConverter method override. using the givein name to return DependencyProperty /// </summary> /// <param name="context">ITypeDescriptorContext</param> /// <param name="culture">CultureInfo</param> /// <param name="source">Object to convert from</param> /// <returns>instance of Command</returns> public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object source) { return SetterTriggerConditionValueConverter.ResolveValue(context, null, culture, source); } // /// <summary> /// ConvertTo() - Serialization purposes, returns the string from Command.Name by adding ownerType.FullName /// </summary> /// <param name="context">ITypeDescriptorContext</param> /// <param name="culture">CultureInfo</param> /// <param name="value">the object to convert from</param> /// <param name="destinationType">the type to convert to</param> /// <returns>string object, if the destination type is string</returns> public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { throw GetConvertToException(value, destinationType); } #endregion Public Methods internal static object ResolveValue(ITypeDescriptorContext serviceProvider, DependencyProperty property, CultureInfo culture, object source) { ArgumentNullException.ThrowIfNull(serviceProvider); ArgumentNullException.ThrowIfNull(source); // Only need to type convert strings and byte[] if (!(source is byte[] || source is String || source is Stream)) { return source; } IXamlSchemaContextProvider ixsc = (serviceProvider.GetService(typeof(IXamlSchemaContextProvider)) as IXamlSchemaContextProvider); if (ixsc == null) { throw new NotSupportedException(SR.Format(SR.ParserCannotConvertPropertyValue, "Value", typeof(Object).FullName)); } XamlSchemaContext schemaContext = ixsc.SchemaContext; if (property != null) { //Get XamlMember from dp System.Xaml.XamlMember xamlProperty = schemaContext.GetXamlType(property.OwnerType).GetMember(property.Name); if (xamlProperty == null) xamlProperty = schemaContext.GetXamlType(property.OwnerType).GetAttachableMember(property.Name); System.Xaml.Schema.XamlValueConverter<TypeConverter> typeConverter = null; if (xamlProperty != null) { // If we have a Baml2006SchemaContext and the property is of type Enum, we already know that the // type converter must be the EnumConverter. if (xamlProperty.Type.UnderlyingType.IsEnum && schemaContext is Baml2006.Baml2006SchemaContext) { typeConverter = XamlReader.BamlSharedSchemaContext.GetTypeConverter(xamlProperty.Type.UnderlyingType); } else { typeConverter = xamlProperty.TypeConverter; if (typeConverter == null) { typeConverter = xamlProperty.Type.TypeConverter; } } } else { typeConverter = schemaContext.GetXamlType(property.PropertyType).TypeConverter; } // No Type converter case... if (typeConverter.ConverterType == null) { return source; } TypeConverter converter = null; if (xamlProperty != null && xamlProperty.Type.UnderlyingType == typeof(Boolean)) { if (source is String) { converter = new BooleanConverter(); } else if (source is byte[]) { byte[] bytes = source as byte[]; if (bytes != null && bytes.Length == 1) { return (bytes[0] != 0); } else { throw new NotSupportedException(SR.Format(SR.ParserCannotConvertPropertyValue, "Value", typeof(Object).FullName)); } } else { throw new NotSupportedException(SR.Format(SR.ParserCannotConvertPropertyValue, "Value", typeof(Object).FullName)); } } else { converter = (TypeConverter)typeConverter.ConverterInstance; } return converter.ConvertFrom(serviceProvider, culture, source); } else { return source; } } } } |