2015-03-28 15 views
5

Próbuję utworzyć niestandardowy selektor z 3 komponentami. Poszedłem za tutorialem na stronie Xamarin here. Dostałem kontrolę do pracy, chyba że kliknę przycisk "Gotowe" na selektorze (jest to domyślny przycisk zakończenia). Dostaję następujący wyjątek:Próba utworzenia niestandardowego selektora w Xamarin Forms

System.InvalidCastException: Nie można rzucić obiektu typu "myproj.iOS.MyPickerModel", aby wpisać "Xamarin.Forms.Platform.iOS.PickerRenderer + PickerSource".

Oto mój kod:

W udostępnionym proj:

public class MyPicker: Picker {} 

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

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

I wreszcie moja strona:

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

Nie rozumiem, dlaczego jej próbuje rzucić MyPickerModel do PickerRenderer + PickerSource

Dzięki!

Odpowiedz

1

Nie wiem, jak IOS działa, ale wygląda jak moja wersja Androida ma pokazuje co trzeba:

Moja basePicker wygląda następująco:

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

Moja platforma szczególne widzenia wygląda następująco:

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

Wygląda na to, że musisz zmienić swój

być

var picker = (MyPicker)this.Element; 

Wtedy właśnie porządkowy co trzeba stamtąd może dodać odwołanie do modelu

4

Byłaś prawie ... Wystarczy utworzyć nową instancję UIPickerView przypisać swój zwyczaj model (MyPickerModel) do niego, a następnie przypisz UIPickerView do Control.InputView. OnElementChanged w swoim rendererze będzie wyglądać następująco:

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; 
     }; 
    } 
} 
Powiązane problemy