2015-03-28 9 views
5

Sto provando a creare un selettore personalizzato con 3 componenti. Ho seguito il tutorial sul sito Xamarin here. Ho ottenuto il controllo per funzionare, tranne quando faccio clic sul pulsante Fatto sul selettore (Questo è il pulsante predefinito fatto). Ricevo la seguente eccezione:Cercando di creare un selettore personalizzato in Xamarin Forms

System.InvalidCastException: impossibile eseguire il cast dell'oggetto di tipo "myproj.iOS.MyPickerModel" per digitare "Xamarin.Forms.Platform.iOS.PickerRenderer + PickerSource".

Ecco il mio codice:

Nella proj comune:

public class MyPicker: Picker {} 

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

e il modello:

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

E infine la mia pagina:

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

non capisco il motivo per cui il suo tentativo di lanciare MyPickerModel a PickerRenderer + PickerSource

Grazie!

risposta

1

Non sono sicuro di come funziona IOS, ma sembra che la mia versione Android ha mostra quello che vi serve:

mio basePicker si presenta così:

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

La mia piattaforma specifica vista assomiglia:

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

In base all'aspetto, devi cambiare la tua

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

di essere

var picker = (MyPicker)this.Element; 

Poi basta refence quello che ti serve da lì forse aggiungere un riferimento al modello

4

Eri quasi ... Basta creare una nuova istanza del UIPickerView, assegnare la vostra abitudine modello (MyPickerModel) ad esso e quindi assegnare il UIPickerView a Control.InputView. OnElementChanged nel tuo renderer sarebbe simile a questo:

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 e.g. "SelectedValueChanged"... 
     myPickerModel.SelectedValueChanged += (sender, eventArgs) => 
     { 
      //...to set the selected value as title of the picker element 
      e.NewElement.Title = myPickerModel.SelectedValue; 
     }; 
    } 
} 
Problemi correlati