iOS项目中基于Xamarin.Forms.Maps在CustomMapRenderer类中跨方法调用对象及解决Pin点击时数据库查询的CS0103错误
先快速搞定那个CS0103错误,再调整逻辑实现点击Pin才查数据库的需求:
1. 修复CS0103: The name 'annotation' does not exist in the current context
你在修改后的OnDidSelectAnnotationView里直接用了annotation变量,但这个变量在当前方法的上下文里根本没定义!要获取选中的标注对象,得从事件参数的e.View.Annotation属性拿——因为e.View就是被点击的MKAnnotationView,它的Annotation属性对应的就是你要的MKPointAnnotation实例。
把出错的那行代码:
var customPin = GetCustomPin(annotation as MKPointAnnotation);
改成:
var customPin = GetCustomPin(e.View.Annotation as MKPointAnnotation);
2. 调整逻辑:仅在点击Pin时执行数据库查询
原来的GetCustomPin方法在地图加载标注时(也就是应用启动阶段)就会触发数据库查询,这不符合你的需求。现在我们把数据库查询逻辑从GetCustomPin里剥离出来,让它只负责匹配对应的CustomPin对象,查询操作放到OnDidSelectAnnotationView中,这样只有点击Pin时才会执行查询。
修改后的GetCustomPin方法
移除里面的数据库查询和MessagingCenter发送代码,只保留查找CustomPin的核心逻辑:
CustomPin GetCustomPin(MKPointAnnotation annotation) { var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude); foreach (var pin in customPins) { if (pin.Position == position) { return pin; // 只返回匹配的CustomPin,不再在这里触发数据库操作 } } return null; }
修改后的OnDidSelectAnnotationView方法
整合查询逻辑,同时保留原来的信息窗口展示功能:
void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e) { CustomMKAnnotationView customView = e.View as CustomMKAnnotationView; customPinView = new UIView(); // 获取对应的CustomPin并做空判断,避免空引用错误 var selectedAnnotation = e.View.Annotation as MKPointAnnotation; var customPin = GetCustomPin(selectedAnnotation); if (customPin != null) { // 点击Pin时才执行数据库查询 int mapCode = int.Parse(customPin.CodeNum.ToString()); var result = DataBaseConnection(mapCode); MessagingCenter.Send<object, IEnumerable<AlertLevel>>(this, "PinSelected", result); } // 保留原有的信息窗口展示逻辑 if (customView != null && customView.Name.Equals("Xamarin")) { customPinView.Frame = new CGRect(0, 0, 200, 84); customPinView.Center = new CGPoint(0, -(e.View.Frame.Height + 75)); var labelAlertLevel = new UILabel(new CGRect(60, 0, 200, 84)); labelAlertLevel.Text = "Код на трвога (1-4): " + customView.AlertLevel.ToString(); customPinView.AddSubview(labelAlertLevel); var labelCodeNum = new UILabel(new CGRect(60, 20, 200, 84)); labelCodeNum.Text = "Код на станция: " + customView.CodeNum.ToString(); customPinView.AddSubview(labelCodeNum); e.View.AddSubview(customPinView); } }
额外小提示
建议始终保留空引用判断(比如customPin != null),避免因为找不到匹配的CustomPin导致崩溃;另外DataBaseConnection方法里的SQL语句要注意防止注入风险,如果mapCode是外部传入的,最好用参数化查询替代字符串拼接。
这样修改后,既解决了CS0103错误,又实现了仅点击Pin时触发数据库查询的需求,同时保留了原有的信息窗口展示功能。
内容的提问来源于stack exchange,提问作者Pizhev Racing

