如何在整个WPF渲染周期内显示等待光标?
WPF全渲染周期等待光标设置可用事件列表
触发时机捕获事件
- 自定义可触发重绘的依赖属性变更回调:比如你提到的边框
StrokeWidth这类属性的PropertyChangedCallback,是最早捕获重绘触发的节点,可直接在回调内设置Mouse.OverrideCursor = Cursors.Wait。 - 布局容器的
FrameworkElement.SizeChanged事件:如果是容器尺寸变更触发的全量重绘,可通过AddHandler方法注册该事件,设置handledEventsToo为true避免内部控件吞掉事件。 - 数据源变更事件:如果是层级数据源刷新触发的控件重绘,可监听对应数据源的
INotifyPropertyChanged.PropertyChanged或INotifyCollectionChanged.CollectionChanged事件作为触发点。
渲染完成监听事件
UIElement.LayoutUpdated事件:该事件会在当前视觉树的Measure、Arrange流程全部完成后触发,是确认布局阶段结束的核心事件,需要搭配自定义标志位使用,避免多次触发逻辑。CompositionTarget.Rendering事件:该事件会在WPF每帧渲染到屏幕前触发,要覆盖到最终屏幕输出环节,需要在LayoutUpdated触发后监听一次CompositionTarget.Rendering,再通过DispatcherPriority.Render优先级的调度恢复光标,就能保证等待光标覆盖全渲染周期。
示例代码
private bool _isWaitingForRender; // 重绘触发时调用 private void StartWaitForRender() { if (_isWaitingForRender) return; _isWaitingForRender = true; Mouse.OverrideCursor = Cursors.Wait; LayoutUpdated += OnLayoutCompleted; } private void OnLayoutCompleted(object sender, EventArgs e) { LayoutUpdated -= OnLayoutCompleted; // 等待下一帧渲染完成后恢复光标 CompositionTarget.Rendering += OnFrameRendered; } private void OnFrameRendered(object sender, EventArgs e) { CompositionTarget.Rendering -= OnFrameRendered; // 确保渲染队列所有任务执行完成 Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => { Mouse.OverrideCursor = null; _isWaitingForRender = false; })); }
注意:不要在
MeasureOverride、ArrangeOverride方法内设置光标,两个方法会被频繁调用,容易导致光标闪烁。
内容的提问来源于stack exchange,提问作者AxD
相关产品推荐
相关产品推荐

