Xamarin.Forms中DevExpress DataGridView Tap触发对象引用未设置错误
Xamarin.Forms 真机APK空引用错误排查(模拟器调试正常)
问题背景
开发Xamarin.Forms查询页面,通过动态对象自动生成DevExpress DataGridView实现查询参数复用与切换。模拟器调试时功能正常,但将Visual Studio生成的APK安装到真机后,触发「未将对象引用设置到对象实例」错误,无法定位具体问题点。相关点击事件代码如下:
private async void dataTable_Tap(object sender, DevExpress.XamarinForms.DataGrid.DataGridGestureEventArgs e) { try { var menuItem = (DevExpress.XamarinForms.DataGrid.DataGridView)sender; if (menuItem != null) { if (e != null) { dynamic dItem = e.Item; if (dItem != null) { string queryParameter = Preferences.Get("queryParameters", ""); queryParameter += dItem[vNumber] + pid + ";;"; Preferences.Set("queryParameters", queryParameter); Console.WriteLine(queryParameter); await PopupNavigation.Instance.PopAsync(); DependencyService.Get<IMessage>().UzunMesaj($"{dItem[vNumber]}"); } } } } catch (Exception ex) { await DisplayAlert("", $"Can not select : \n{ex.Message}", "Tmm"); throw; } }
可能的错误原因及解决方案
1. 动态对象dItem的运行时绑定问题
Release模式下(APK默认是Release编译),编译器优化可能导致动态对象的成员访问失效,而Debug模式的模拟器会保留更多运行时绑定信息。
- 替代方案:将动态对象转为
IDictionary<string, object>(如果e.Item是匿名类型或字典),通过键值对安全访问成员:if (e.Item is IDictionary<string, object> itemDict) { if (itemDict.TryGetValue(vNumber, out var vNumberValue) && vNumberValue != null) { // 后续逻辑使用vNumberValue } }
2. PopupNavigation.Instance未初始化
真机环境中,PopupNavigation的实例可能未被正确初始化,导致调用PopAsync()时空引用。
- 解决方案:调用前先判空:
if (PopupNavigation.Instance != null) { await PopupNavigation.Instance.PopAsync(); }
3. DependencyService.Get<IMessage>()返回null
Release模式下链接器可能移除了IMessage的实现类,或者未正确注册依赖服务。
- 解决方案:
- 在平台项目的实现类上添加
[assembly: Dependency(typeof(MessageImplementation))]特性; - 在Release链接器设置中排除相关程序集,或给实现类添加
[Preserve]特性避免被优化移除。
- 在平台项目的实现类上添加
4. pid变量未初始化
代码中直接使用pid变量,但未展示其赋值逻辑,若pid为null,字符串拼接时会引发空引用。
- 解决方案:使用前确保
pid有值,或默认空字符串:string pidValue = pid ?? string.Empty; queryParameter += $"{vNumberValue}{pidValue};;";
5. 真机调试定位具体错误
最直接的方式是开启真机调试:
- 在Visual Studio中选择真机作为调试目标,部署APK并启动调试;
- 触发错误时,查看调用栈定位具体空引用的代码行;
- 关键步骤添加日志输出(如
Console.WriteLine),通过Android Logcat或iOS Console查看真机日志。
修改后的示例代码
private async void dataTable_Tap(object sender, DevExpress.XamarinForms.DataGrid.DataGridGestureEventArgs e) { try { if (sender is not DevExpress.XamarinForms.DataGrid.DataGridView) return; if (e?.Item == null) return; if (e.Item is IDictionary<string, object> itemDict) { if (!itemDict.TryGetValue(vNumber, out var vNumberValue) || vNumberValue == null) { await DisplayAlert("", "无法获取指定参数", "确定"); return; } string pidValue = pid ?? string.Empty; string queryParameter = Preferences.Get("queryParameters", ""); queryParameter += $"{vNumberValue}{pidValue};;"; Preferences.Set("queryParameters", queryParameter); Console.WriteLine(queryParameter); if (PopupNavigation.Instance != null) { await PopupNavigation.Instance.PopAsync(); } var messageService = DependencyService.Get<IMessage>(); messageService?.UzunMesaj($"{vNumberValue}"); } else { await DisplayAlert("", "数据格式不支持", "确定"); } } catch (Exception ex) { await DisplayAlert("", $"选择失败:\n{ex.Message}", "确定"); } }
内容的提问来源于stack exchange,提问作者Mert Altiparmak
相关产品推荐
相关产品推荐

