调用DisplayPromptAsync后SelectedItem变量被置空的问题求助
问题:执行DisplayPromptAsync后SelectedItem变量被置为null
我完全搞不懂为什么SelectedItem变量会变成null。这个对象本来已经赋值了,但调用DisplayPromptAsync之后就被置空了。之前从来没碰到过这种问题,不知道该怎么排查。

相关代码如下:
async void OpenContainerItem() { // Pause the timer blnTimerActive = false; if (SelectedItem != null) { if (SelectedItem.intQuanChecked == SelectedItem.intQuantity) return; try { int intQuantity = 0; // Ask for quantity string result = await Application.Current.MainPage.DisplayPromptAsync("Quantity", "How many " + SelectedItem.objItem.strItemName + " did you count?", "Okay", cancel: "Cancel", placeholder: "Quantity", keyboard: Keyboard.Numeric); // Check if it's been cancelled if (result != null) { // check if theres nothing entered if (result == "") { // Why tho? await Application.Current.MainPage.DisplayAlert("Error", "Please enter a quantity.", "Okay"); } else { intQuantity = int.Parse(result); if (0 > ((SelectedItem.intQuantity - SelectedItem.intQuanChecked) - intQuantity)) { Application.Current.MainPage.DisplayAlert("Error", "Thats too many items!", "Okay"); Reload(); blnTimerActive = true; return; } modDatabaseUtilities.ContainerItemsPreCheck(SelectedItem.intContainerItemID, intQuantity, strCurrentUser); Reload(); } } } catch(Exception ex) { Application.Current.MainPage.DisplayAlert("Error", "Couldn't process this change. Please try again.", "Okay"); } } }
排查方向与解决方法
1. 缓存SelectedItem避免UI绑定重置
DisplayPromptAsync会触发UI线程状态更新,如果SelectedItem是绑定到UI控件的属性,弹窗关闭后UI重新绑定可能导致原对象被重置。解决思路是调用弹窗前先把SelectedItem缓存到局部变量,后续操作都引用这个缓存:
async void OpenContainerItem() { // 提前缓存当前选中项 var currentSelectedItem = SelectedItem; blnTimerActive = false; if (currentSelectedItem != null) { if (currentSelectedItem.intQuanChecked == currentSelectedItem.intQuantity) return; try { int intQuantity = 0; string result = await Application.Current.MainPage.DisplayPromptAsync("Quantity", "How many " + currentSelectedItem.objItem.strItemName + " did you count?", "Okay", cancel: "Cancel", placeholder: "Quantity", keyboard: Keyboard.Numeric); if (result != null) { if (result == "") { await Application.Current.MainPage.DisplayAlert("Error", "Please enter a quantity.", "Okay"); } else { intQuantity = int.Parse(result); if (0 > ((currentSelectedItem.intQuantity - currentSelectedItem.intQuanChecked) - intQuantity)) { Application.Current.MainPage.DisplayAlert("Error", "Thats too many items!", "Okay"); Reload(); blnTimerActive = true; return; } modDatabaseUtilities.ContainerItemsPreCheck(currentSelectedItem.intContainerItemID, intQuantity, strCurrentUser); Reload(); } } } catch(Exception ex) { Application.Current.MainPage.DisplayAlert("Error", "Couldn't process this change. Please try again.", "Okay"); } } }
2. 检查Reload()方法的影响
代码中调用的Reload()方法可能会重新加载数据源,导致原来的SelectedItem对象脱离数据源,进而被置为null。可以查看Reload()的实现逻辑,确认是否需要在重新加载后恢复选中状态,或者调整该方法的调用时机。
3. 修正异步方法签名
当前方法用了async void,这种签名多用于事件处理,容易导致上下文丢失或异常无法捕获。建议改成async Task,调用时使用await OpenContainerItem(),避免异步操作的上下文异常:
async Task OpenContainerItem() { // 方法逻辑不变,仅修改签名 }
内容的提问来源于stack exchange,提问作者Scott Uphus
相关产品推荐
相关产品推荐

