Trying to create a custom assembler in Xamarin Forms

I am trying to create my own assembler with three components. I followed the tutorial on the Xamarin website here . I got control over the work, except when I click the "Finish" button on the collector (this is the default button). I get the following exception:

System.InvalidCastException: it is not possible to throw an object of type 'myproj.iOS.MyPickerModel' to enter 'Xamarin.Forms.Platform.iOS.PickerRenderer + PickerSource'.

Here is my code:

In general proj:

public class MyPicker: Picker {} 

In iOS proj:

 [assembly: ExportRenderer(typeof(MyPicker), typeof(MyPickerRenderer))] public class MyPickerRenderer: PickerRenderer { // Override the OnElementChanged method so we can tweak this renderer post-initial setup protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) { base.OnElementChanged(e); if (Control != null) { var picker = (UIPickerView)this.Control.InputView; picker.BackgroundColor = UIColor.White; picker.Model = new MyPickerModel(); } 

And the model:

 public class MyPickerModel : UIPickerViewModel { private string[] array1 = new string [] { "1","2","3","4" }; private string[] array2 = new string [] { "1a","2a","3a","4a" }; private string[] array3 = new string [] { "a","b","c","d" }; public override nint GetComponentCount (UIPickerView pickerView) { return 3; } public override nint GetRowsInComponent (UIPickerView pickerView, nint component) { // Returns switch (component) { case 0: return array1.Length; case 1: return array2.Length; case 2: return array3.Length; default:break; } return 0; } public override string GetTitle (UIPickerView pickerView, nint row, nint component) { // Returns switch (component) { case 0: return array1[row]; case 1: return array2[row]; case 2: return array3[row]; default: break; } return null; } public override nfloat GetComponentWidth (UIPickerView pickerView, nint component) { switch (component) { case 0: return 100.0f; case 1: return 100.0f; case 2: return 100.0f; default: break; } return 0; } public override nfloat GetRowHeight (UIPickerView pickerView, nint component) { return 40f; } } 

And finally, my page:

 public class MyPage : ContentPage { public MyPage() { MyPicker picker = new MyPicker { Title = "Color", VerticalOptions = LayoutOptions.CenterAndExpand }; picker.SelectedIndexChanged += (sender, args) => { }; var mainLayout = new StackLayout { Orientation = StackOrientation.Vertical, Children = { picker } }; // Accomodate iPhone status bar. this.Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0); this.BackgroundImage = "background.png"; // Build the page. this.Content = mainLayout; } } 

I do not understand why it is trying to use MyPickerModel for PickerRenderer + PickerSource

Thanks!

+5
source share
2 answers

You were almost there ... Just create a new instance of UIPickerView , assign it your custom model ( MyPickerModel ), and then assign UIPickerView Control.InputView . OnElementChanged in your renderer will look like this:

 protected override void OnElementChanged(ElementChangedEventArgs<Picker> e) { base.OnElementChanged(e); if (Control != null) { var myPickerModel = new MyPickerModel(); var myPickerView = new UIPickerView { Model = myPickerModel }; //Assign your picker view Control.InputView = myPickerView; //You can also create an event in your model to react on user actions like eg "SelectedValueChanged"... myPickerModel.SelectedValueChanged += (sender, eventArgs) => { //...to set the selected value as title of the picker element e.NewElement.Title = myPickerModel.SelectedValue; }; } } 
+4
source

I don't know how iOS works, but it looks like my version of Android shows what you need:

My basePicker looks like this:

  public class BaseBindablePicker : Picker { public static readonly BindableProperty BackgroundColor= BindableProperty.Create<BaseBindablePicker, Color>(p => p.BackgroundColor, Color.Default); public Color ColorBackground { get { return (Color)base.GetValue(BackgroundColor); } set { base.SetValue(BackgroundColor, value); } } } 

The view of my platform is as follows:

 [assembly: ExportRenderer(typeof(BaseBindablePicker), typeof(SimpleEID.Android.Shared.CustomRender.AndroidPicker))] public class AndroidPicker : PickerRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Picker> e) { base.OnElementChanged(e); var pick = (BaseBindablePicker)this.Element; this.Control.SetBackgroundColor(pick.BackColor.ToAndroid()); } } 

It basically looks like you need to change

 var picker = (UIPickerView)this.Control.InputView; 

to be

 var picker = (MyPicker)this.Element; 

Then just confirm what you need, maybe add a link to your model.

+1
source

Source: https://habr.com/ru/post/1216335/


All Articles