【问题标题】:Trying to create a custom picker in Xamarin Forms尝试在 Xamarin Forms 中创建自定义选择器
【发布时间】:2015-06-01 13:02:33
【问题描述】:

我正在尝试创建一个包含 3 个组件的自定义选择器。我按照 Xamarin 网站 here 上的教程进行操作。我让控件工作,除非我单击选择器上的完成按钮(这是默认的完成按钮)。我得到以下异常:

System.InvalidCastException:无法将“myproj.iOS.MyPickerModel”类型的对象转换为“Xamarin.Forms.Platform.iOS.PickerRenderer+PickerSource”类型。

这是我的代码:

在共享项目中:

public class MyPicker: Picker {}

在 iOS 项目中:

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

还有模特:

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

最后是我的页面:

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

我不明白为什么它试图将 MyPickerModel 转换为 PickerRenderer+PickerSource

谢谢!

【问题讨论】:

    标签: xamarin xamarin.forms


    【解决方案1】:

    您快到了...只需创建UIPickerView 的新实例,将您的自定义模型(MyPickerModel)分配给它,然后将UIPickerView 分配给Control.InputView。渲染器中的OnElementChanged 将如下所示:

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

    【讨论】:

      【解决方案2】:

      不确定 IOS 是如何工作的,但看起来我的 android 版本已经显示了您需要的内容:

      我的 basePicker 看起来像这样:

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

      我的平台特定视图如下所示:

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

      基本上看起来你需要改变你的

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

      成为

      var picker = (MyPicker)this.Element;
      

      然后只需从那里引用您需要的内容,也许可以添加对您的模型的引用

      【讨论】:

        猜你喜欢
        • 2022-01-02
        • 1970-01-01
        • 2017-12-21
        • 2020-03-19
        • 2018-12-25
        • 1970-01-01
        • 2020-12-10
        • 2019-04-06
        • 1970-01-01
        相关资源
        最近更新 更多