何时及为何访问CoreWindow.ActivationMode会抛出InvalidCastException?
解决W10M设备中访问CoreWindow.ActivationMode抛出InvalidCastException的问题
这个问题确实挺让人头疼的——官方文档明明没标注ActivationMode会抛出异常,但在W10M的ScrollViewer滚动场景下却偶发InvalidCastException。结合W10M移动设备的UI线程特性和滚动时的状态变化,我整理了几个可行的解决方案:
一、先做异常捕获兜底
既然异常是偶发的,首先要做的就是避免崩溃,同时降级处理焦点判断逻辑:
CoreWindow window = Window.Current.CoreWindow; bool isWindowInFocus = false; try { CoreWindowActivationMode mode = window.ActivationMode; // 通过激活模式判断窗口是否在前台 isWindowInFocus = mode == CoreWindowActivationMode.ActivatedInForeground; } catch (InvalidCastException) { // 异常时用其他方式间接判断,比如指针激活状态 isWindowInFocus = window.PointerActivated; } // 后续使用isWindowInFocus做业务逻辑
二、延迟执行焦点判断
ScrollViewer的ViewChanged事件会在滚动过程中高频触发,此时UI线程可能处于忙碌状态,窗口内部状态还未稳定。可以借助Dispatcher延迟到UI线程空闲时再获取激活状态:
private async void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { // 可选:只在滚动结束时判断,减少不必要的回调 if (!e.IsIntermediate) { await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Low, () => { CoreWindow window = Window.Current.CoreWindow; try { CoreWindowActivationMode mode = window.ActivationMode; // 处理你的业务逻辑 } catch (InvalidCastException) { // 异常降级处理 } }); } }
三、换一种焦点判断思路
放弃直接读取ActivationMode,改为通过监听窗口激活事件维护全局状态变量,这样在滚动事件里直接读取变量即可:
private bool _isWindowActive = false; // 在页面初始化/应用启动时注册监听 private void SetupWindowActivationListener() { CoreWindow.GetForCurrentThread().Activated += (sender, args) => { _isWindowActive = args.WindowActivationState == CoreWindowActivationState.Activated; }; } // 在ViewChanged事件中直接使用状态变量 private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e) { if (_isWindowActive) { // 窗口处于激活状态的逻辑 } else { // 窗口未激活的逻辑 } }
额外建议
如果你的ListView开启了虚拟化(IsItemVirtualizing="True"),可以尝试调整虚拟化策略或者滚动阈值——有时候虚拟化加载内容时的滚动会触发特殊的UI状态波动,可能间接导致这个异常出现。
内容的提问来源于stack exchange,提问作者Benni
相关产品推荐
相关产品推荐

