You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin跨视图访问数据问题求助:空引用异常解决

嘿,这个System.NullReferenceException的问题我太熟了!本质原因很简单——你在当前显示的Main布局里,试图去查找另一个还没加载到Activity里的布局中的EditText控件,FindViewById找不到这些控件就会返回null,之后访问.Text自然就抛出空引用异常了。

问题根源拆解

你当前的代码逻辑有个明显的误区:当点击button2时,Activity的ContentView还是Resource.Layout.Main,而addCompany、addDate这些EditText是属于另一个布局(比如你用来添加经验的布局)的,这个布局还没被加载,所以根本找不到这些控件。

两种可行的解决方法

方法一:在同一个Activity中切换布局(适合简单场景)

如果坚持用布局切换的方式,你需要先切换到包含EditText的布局,再去获取控件内容,最后切回Main布局。同时要注意,切换布局后原来的控件会被销毁,切回来需要重新绑定事件:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.Main);
    // 初始化Main布局的事件
    RebindMainLayoutEvents();
}

// 绑定Main布局的按钮事件
private void RebindMainLayoutEvents()
{
    Button button2 = FindViewById<Button>(Resource.Id.addExpereince);
    button2.Click += (sender, e) =>
    {
        // 先切换到添加经验的布局
        SetContentView(Resource.Layout.AddExperience);
        
        // 绑定确认按钮的事件
        Button confirmBtn = FindViewById<Button>(Resource.Id.confirmBtn);
        confirmBtn.Click += (s, args) =>
        {
            // 现在可以找到当前布局里的EditText了
            EditText addCompany = FindViewById<EditText>(Resource.Id.addCompanyName);
            EditText addDate = FindViewById<EditText>(Resource.Id.addDate);
            EditText addPosition = FindViewById<EditText>(Resource.Id.addPosition);
            
            // 先做非空判断,避免异常
            if (addCompany != null && addDate != null && addPosition != null)
            {
                AddExpreince(1, addCompany.Text, addPosition.Text, addDate.Text);
                // 切回Main布局并重新绑定事件
                SetContentView(Resource.Layout.Main);
                RebindMainLayoutEvents();
            }
        };
    };
}

// 你的AddExpreince方法
private void AddExpreince(int id, string company, string position, string date)
{
    // 这里写你的业务逻辑
}

方法二:使用Dialog对话框收集输入(更推荐)

这种方式不需要切换Activity布局,直接弹出一个对话框让用户输入信息,体验更流畅,代码也更简洁:

protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    SetContentView(Resource.Layout.Main);
    
    Button button2 = FindViewById<Button>(Resource.Id.addExpereince);
    button2.Click += (sender, e) =>
    {
        // 创建对话框构建器
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.SetTitle("添加工作经验");
        
        // 加载对话框的自定义布局(需要先创建一个包含三个EditText的布局文件,比如dialog_add_experience.axml)
        View dialogView = LayoutInflater.Inflate(Resource.Layout.dialog_add_experience, null);
        builder.SetView(dialogView);
        
        // 获取对话框里的EditText控件
        EditText addCompany = dialogView.FindViewById<EditText>(Resource.Id.addCompanyName);
        EditText addDate = dialogView.FindViewById<EditText>(Resource.Id.addDate);
        EditText addPosition = dialogView.FindViewById<EditText>(Resource.Id.addPosition);
        
        // 设置确认按钮
        builder.SetPositiveButton("确认", (s, args) =>
        {
            // 可以加个简单的非空校验
            if (!string.IsNullOrWhiteSpace(addCompany.Text) && 
                !string.IsNullOrWhiteSpace(addDate.Text) && 
                !string.IsNullOrWhiteSpace(addPosition.Text))
            {
                AddExpreince(1, addCompany.Text, addPosition.Text, addDate.Text);
            }
        });
        
        // 设置取消按钮
        builder.SetNegativeButton("取消", (s, args) => { /* 对话框关闭,无需操作 */ });
        
        // 显示对话框
        builder.Show();
    };
}

private void AddExpreince(int id, string company, string position, string date)
{
    // 你的业务逻辑代码
}
关键注意事项
  • FindViewById只能查找当前Activity已加载布局中的控件,或者通过LayoutInflater加载的独立View对象(比如对话框的View)里的控件。
  • 用布局切换的方式时,每次切换布局都会销毁之前的控件,所以切回原布局后必须重新绑定所有控件的事件。
  • 优先选择对话框的方式,不仅代码更简洁,还能避免布局切换带来的控件重建、状态丢失等问题,用户体验也更好。

内容的提问来源于stack exchange,提问作者TurhanG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:43:26