I am attempting to create a custom BindableProperty for a custom view which takes in a string when consumed through XAML but is internally implemented as a custom structure as follows:

struct X {
   public Y A;
   public Z B;
   // Y and Z are data types
   // pertaining to a struct
}
public class MyView : CustomView {
  public static readonly BindableProperty 
      MyValueProperty = BindableProperty.Create
                         (propertyName: "MyValue",
                          returnType: typeof(string),
                          declaringType: typeof(MyView),
                          defaultValue: null,
                          defaultBindingMode: BindingMode.TwoWay,
                          propertyChanged: MyValuePropertyChanged);
  static void MyValuePropertyChanged(BindableObject obj, object oldValue, object newValue) {
    MyView view = (MyView)obj;
    string enteredStringValue = (string)newValue;
    // Set the MyValue field as required
  }
  public X MyValue {
      // Implement getters and setters
  }
}

My initial instinct to create the aforementioned property was to declare the above fields and generate the required instance of struct X with respect to the string passed in XAML in the MyValuePropertyChanged method, but it is deemed impossible as an exception is thrown during runtime denoting the illegality of such declaration.

In synopsis, I am attempting to replicate the behavior of the Xamarin.Forms.GridLength structure whose string representations in XAML code is converted to the required structure when accessed through the getters and setters.

Thanks in advance.

1

There are 1 best solutions below

0
On

The said behavior can be implemented by defining a custom type converter via inheritance of the Xamarin.Forms.TypeConverter class and decorating the aforementioned custom converter by the Xamarin.Forms.Xaml.TypeConversion attribute and the concerned structure by the Xamarin.Forms.TypeConverter attribute as follows:

public static readonly BindableProperty 
      MyValueProperty = BindableProperty.Create
                         (propertyName: nameof(MyValue),
                          returnType: typeof(X),
                          declaringType: typeof(MyView),
                          defaultValue: null,
                          defaultBindingMode: BindingMode.TwoWay,
                          propertyChanged: MyValuePropertyChanged);
[TypeConverter(typeof(XConverter))]
struct X; // Declaration omitted in answer

[TypeConversion(typeof(X))]
class XConverter : TypeConverter {
   public override object 
        ConvertFromInvariantString(string value) {
      if (value == null) return null;
      
      // Return the object corresponding to the passed
      // string representation of the said object
   }
}

A predefined converter by Xamarin can also be used when needed as follows:

public static readonly BindableProperty
   SizeProperty = BindableProperty.Create
                  (propertyName: nameof(Size),
                   returnType: typeof(double),
                   declaringType: typeof(TestClass));
[TypeConverter(typeof(Xamarin.Forms.FontSizeConverter))]
public double Size {
   get => (double)GetValue(SizeProperty);
   set => SetValue(SizeProperty, value);
}