C# Xamarin Forms-Droid:定制选取器';导致异常的对话框:对象引用未设置为对象的实例

C# Xamarin Forms-Droid:定制选取器';导致异常的对话框:对象引用未设置为对象的实例,c#,xamarin,xamarin.forms,xamarin.android,nullreferenceexception,C#,Xamarin,Xamarin.forms,Xamarin.android,Nullreferenceexception,背景说明 我正在使用Visual Studio for Mac开发一个跨平台的移动应用程序。该项目的Xamarin.Forms版本是3.1.0.583944(这是最新的可用版本)。对于Android,所有的输入组件都有一个框的行(uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu 在项目文件夹中创建了CustomPicker.cs: using Sys

背景说明

我正在使用Visual Studio for Mac开发一个跨平台的移动应用程序。该项目的Xamarin.Forms版本是3.1.0.583944(这是最新的可用版本)。对于Android,所有的输入组件都有一个框的行(uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

在项目文件夹中创建了CustomPicker.cs:

using System;
using Xamarin.Forms;

namespace Project
{
    public class CustomPicker : Picker
    {
        public Color BorderColor { get; set; } = Color.Black;
    }
}
using System;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Views;
using Project;
using Project.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace Project.Droid
{
    public class CustomPickerRenderer : PickerRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                var customPicker = (CustomPicker)e.NewElement;
                GradientDrawable gd = new GradientDrawable();
                gd.SetColor(Android.Graphics.Color.Transparent);
                gd.SetStroke(2, customPicker.BorderColor.ToAndroid());
                this.Control.SetBackground(gd);
                this.Control.SetTextColor(e.NewElement.TextColor.ToAndroid());
                this.Control.SetHintTextColor(Android.Graphics.Color.Gray);
            }
        }
    }
}
并在Project.Droid文件夹中创建CustomPickerRenderer.cs:

using System;
using Xamarin.Forms;

namespace Project
{
    public class CustomPicker : Picker
    {
        public Color BorderColor { get; set; } = Color.Black;
    }
}
using System;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Views;
using Project;
using Project.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomPicker), typeof(CustomPickerRenderer))]
namespace Project.Droid
{
    public class CustomPickerRenderer : PickerRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
        {
            base.OnElementChanged(e);
            if (Control != null)
            {
                var customPicker = (CustomPicker)e.NewElement;
                GradientDrawable gd = new GradientDrawable();
                gd.SetColor(Android.Graphics.Color.Transparent);
                gd.SetStroke(2, customPicker.BorderColor.ToAndroid());
                this.Control.SetBackground(gd);
                this.Control.SetTextColor(e.NewElement.TextColor.ToAndroid());
                this.Control.SetHintTextColor(Android.Graphics.Color.Gray);
            }
        }
    }
}
(Android.Content.IDialogInterface对话框,System.Int32) [0x0000a]英寸 /Users/builder/data/lanes/5809/a7829590/source/monodroid/external/xamarin-android/src/Mono.android/obj/Release/android-27/mcw/android.Content.IDialogInterface.cs:250

at Android.Content.IDialogInterfaceOnClickListenerInvoker.n_OnClick_Landroid_content_DialogInterface_I
(System.IntPtr jnienv,System.IntPtr native_u_uthis,System.IntPtr 本机_对话框,System.Int32,其中[0x00010]位于 /Users/builder/data/lanes/5809/a7829590/source/monodroid/external/xamarin-android/src/Mono.android/obj/Release/android-27/mcw/android.Content.IDialogInterface.cs:201

at (wrapper dynamic-method) System.Object.b72d5cd8-e4b0-403b-a87c-7a28c7960847(intptr,intptr,intptr,int)
尝试了什么

在网上搜索,我找到了许多可能的解决方案,但不幸的是,没有一个对我有效:

  • 向OnElementChanged函数添加try-catch
  • 其他可能的解决方案我甚至不记得了,也找不到它们的链接(因为我打开了大量链接)
问题

  • 如何处理此异常
  • 自定义选择器渲染器实现是否可能在没有此崩溃的情况下实现,或者我将被迫使用原始组件
  • 有没有办法访问错误堆栈(Xamarin.Forms.Platform.Android.PickerRenderer+c_udisplayClass12_0)中描述的OnClick事件

  • 在此问题上的任何帮助都将不胜感激。提前感谢所有愿意花时间阅读这篇长文章并尝试提供帮助的人。

    在Android上,您可以在自定义渲染器中使用SetOnClickListener实现OnClick事件,这里有一个示例:@MikeCamo我所做的是删除自定义选择器并使用默认选择器。后来我意识到崩溃是由于对话框造成的。因此,我所做的是在显示对话框之前检查应用程序是否在后台(因此只有当应用程序当前在前台处于活动状态时才会显示)。我刚刚在onStart、onStop、onPause和onResume方法上添加了一个标志来检查应用程序的当前状态。这样做可以防止应用程序在对话框出现中断时崩溃。我希望这对你有帮助。如果你需要更多的信息,请告诉我。我终于能够重现这个问题了。在我的例子中,我让选择器弹出,但我没有禁用页面底部的导航栏。有人可以弹出选择器,但在它显示之前,他们可以从导航栏中选择另一个页面。这将用另一个页面替换当前页面,当他们从选择器中选择一个仍然可见的项目时,会导致异常,因为该页面不再存在。谢谢你的帮助@Thunderlight:)@Mikecaimo很抱歉我不能马上回答,但我很高兴你能重现这个问题。为了回答您之前的问题,我的选取器中没有太多项目,但对我来说,有效的方法是将应用程序部署在低成本手机上(速度明显较慢),这让我有机会中断活动,并导致崩溃。如果你能解决这个问题,请让我知道你是如何做到这一点的。同样欢迎您,很高兴我能帮助您。@mikecamimo关于第二个问题,我在App.cs文件中处理了如下标志:
    protectedoverride void OnStart(){Global.AppInBackground=false;}
    protected override void OnSleep(){Global.AppInBackground=true;}
    protected override void OnResume(){Global.AppInBackground=false;}
    在显示弹出窗口时,只需检查标志以了解应用程序是在前台还是后台。希望这对您有所帮助。