Создание настраиваемого свойства BindableProperty, которое принимает настраиваемое строковое представление базового возвращаемого типа в XAML

#c# #xamarin #xamarin.forms #bindableproperty

#c# #xamarin #xamarin.forms #свойство bindableproperty

Вопрос:

Я пытаюсь создать пользовательское BindableProperty для пользовательского представления, которое принимает строку при использовании через XAML, но внутренне реализовано как настраиваемая структура следующим образом:

 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
  }
}
 

Моим первоначальным побуждением к созданию вышеупомянутого свойства было объявить вышеуказанные поля и сгенерировать требуемый экземпляр struct X в отношении string переданного в XAML в MyValuePropertyChanged методе, но это считается невозможным, поскольку во время выполнения генерируется исключение, обозначающее незаконность такого объявления.

В кратком изложении я пытаюсь воспроизвести поведение Xamarin.Forms.GridLength структуры, строковые представления которой в коде XAML преобразуются в требуемую структуру при доступе к ним через получатели и установщики.

Заранее спасибо.

Ответ №1:

Указанное поведение может быть реализовано путем определения пользовательского преобразователя типов посредством наследования Xamarin.Forms.TypeConverter класса и декорирования вышеупомянутого пользовательского преобразователя Xamarin.Forms.Xaml.TypeConversion атрибутом и соответствующей структуры Xamarin.Forms.TypeConverter атрибутом следующим образом:

 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
   }
}
 

При необходимости можно также использовать предопределенный конвертер от Xamarin следующим образом:

 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);
}