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