0
votes

I'm trying to implement a custom control that derives from DatePicker. This control will have android and iOS renderers. I need to add FontSize property for this control which I will use in renderer classes.

Here is my implementation of the FontSize property:

public static BindableProperty FontSizeProperty = BindableProperty.Create<ExDatePicker, double>(o => o.FontSize, 16d, propertyChanged: OnFontSizeChanged);

public double FontSize
    {
        get { return (double)GetValue(FontSizeProperty); }
        set { SetValue(FontSizeProperty, value); }
    }

private static void OnFontSizeChanged(BindableObject bindable, double oldvalue, double newvalue)
    {
        var control = bindable as ExDatePicker;
        if (control != null)
        {
            control.FontSize = newvalue;
        }
    }

What I need is ability to use this property in the same way as native FontSize properties works, i.e. I need to be able to set something like

FontSize="Small"

in xaml code. Is it possible?

EDIT: In xamarin forms one can use FontSize="Small" to set the device specific font size for different platforms. This autmagically converts the "Small" string into the double using

Device.GetNamedSize(NamedSize.Small, typeof(ExtednedDatePicker))

I don't know how to add this autoconversion for user created FontSize not in Xamarin Forms library

3
In that case could you not have the font size property as an object and in your OnFontSizeChanged method try identify if it is a string or double and if it is a string use a switch statement to set the size?User1
Will check this solutionDzior
try like this in xaml page FontSize="{StaticResource FontSizeSmall}" add this resources <x:Double x:Key="FontSizeSmall">16</x:Double>Jayasri
I've checked the user1 solution. To make this work i would need to change the type of property to object but it needs to be doubleDzior

3 Answers

1
votes

This is how its done with NamedSize in Xamarin Forms.

NamedSize is an Enum and not string. Even though there is a string conversion provided for using in the XAML.

public enum NamedSize
{
    Default = 0,
    Micro = 1,
    Small = 2,
    Medium = 3,
    Large = 4
}

It uses the Device.GetNamedSize() to get the double value from the input value. The Device.GetNamedSize uses platform services or native code to convert.

public class FontSizeConverter : TypeConverter, IExtendedTypeConverter
{
    object IExtendedTypeConverter.ConvertFromInvariantString(string value, IServiceProvider serviceProvider)
    {
        if (value != null)
        {
            double size;
            if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
                return size;
            NamedSize namedSize;
            if (Enum.TryParse(value, out namedSize))
            {
                Type type;
                var valueTargetProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
                type = valueTargetProvider != null ? valueTargetProvider.TargetObject.GetType() : typeof(Label);
                return Device.GetNamedSize(namedSize, type, false);
            }
        }
        throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(double)));
    }

    public override object ConvertFromInvariantString(string value)
    {
        if (value != null)
        {
            double size;
            if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
                return size;
            NamedSize namedSize;
            if (Enum.TryParse(value, out namedSize))
                return Device.GetNamedSize(namedSize, typeof(Label), false);
        }
        throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(double)));
    }
}
0
votes

try this converter

 public object Convert(object value, Type targetType, object parameter, string language)
        {
            return (bool)value ? "22" : "25";
        }

call thsi converter in xaml page

-3
votes

I never tried xamarin before. But I think it would be possible if you use type converters with generic type parameters.

for exmple,

public class StringToDoubleTypeConverter<T> : TypeConverter where T : IConvertible
{
  // Other methods
  ...

  // Returns whether the type converter can convert an object from the specified type 
  // to the type of this converter.
  public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
  {
      return sourceType.GetInterface("IConvertible", false) != null;
  }

  // Returns whether the type converter can convert an object to the specified type.
  public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
  {
      return destinationType.GetInterface("IConvertible", false) != null;
  }

  public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
  {
      try
      {
          var convertible = (IConvertible)value;
          if (convertible != null) return convertible.ToType(typeof(T), culture);
      }
      catch (FormatException)
      {
          if (value != null && value.ToString().Equals("Small"))
          {
              return MyConstants.Small;
          }
          throw;
      }
      return null;
  }

  // Converts the specified value object to the specified type.
  public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
  {
      return ((IConvertible)value).ToType(destinationType, culture);
  }
}

Then use it in your FontSize property.

[TypeConverter(typeof(StringToDoubleTypeConverter<double>))]
public double FontSize
{
    get { return (double)GetValue(FontSizeProperty); }
    set { SetValue(FontSizeProperty, value); }
}

Reference: http://www.kunal-chowdhury.com/2013/02/autotodouble-typeconverter-for-xaml-silverlight-wpdev.html