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
相关产品推荐
相关产品推荐

