You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测FlowDocumentScrollViewer视图中可见的Section?

WPF中检测FlowDocumentScrollViewer内可见的Section

要检测FlowDocumentScrollViewer中当前可视的Section,核心是对比Section的布局区域和滚动控件的可视范围是否存在交集。以下是具体实现方案:

实现步骤

  1. 在ScrollChanged事件中,获取ScrollViewer的可视区域矩形
  2. 遍历FlowDocument中的所有Section,将每个Section的布局坐标转换为相对于ScrollViewer的坐标
  3. 判断Section的矩形区域是否与ScrollViewer的可视区域有重叠,重叠则标记为可见

修改后的后台代码

替换原Sv_ScrollChanged方法,完整代码如下:

using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void FlowDoc_Loaded(object sender, RoutedEventArgs e)
        {
            ScrollViewer sv = flowDoc.Template.FindName("PART_ContentHost", flowDoc) as ScrollViewer;
            sv.ScrollChanged += Sv_ScrollChanged;
        }

        private void Sv_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var scrollViewer = sender as ScrollViewer;
            if (scrollViewer == null) return;

            // 获取ScrollViewer的可视区域
            Rect viewportRect = new Rect(0, scrollViewer.VerticalOffset, scrollViewer.ViewportWidth, scrollViewer.ViewportHeight);

            foreach (Section section in flowdoc1.Blocks)
            {
                // 获取Section的Visual对象
                var visual = section as Visual;
                if (visual == null) continue;

                // 将Section的坐标转换为相对于ScrollViewer的坐标
                GeneralTransform transform = visual.TransformToAncestor(scrollViewer);
                Rect sectionRect = transform.TransformBounds(new Rect(0, 0, section.ActualWidth, section.ActualHeight));

                // 判断是否有交集(即是否可见)
                bool isVisible = viewportRect.IntersectsWith(sectionRect);

                // 这里可以根据isVisible做后续处理,比如打印或标记
                if (isVisible)
                {
                    System.Diagnostics.Debug.WriteLine($"可见Section: {section.Name}");
                }
            }
        }
    }
}

关键代码说明

  • 获取可视区域:通过scrollViewer.VerticalOffset、ViewportWidth和ViewportHeight构建ScrollViewer当前的可视矩形
  • 坐标转换:使用TransformToAncestor将Section自身的布局坐标转换为相对于ScrollViewer的坐标,确保坐标系统统一
  • 交集判断:调用IntersectsWith方法判断两个矩形是否重叠,只要有重叠部分就认为该Section处于可视范围内

如果需要更严格的可见判断(比如Section必须完全在可视区域内),可以将IntersectsWith替换为判断viewportRect.Contains(sectionRect)。

内容的提问来源于stack exchange,提问作者Kiran Shahi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:08:14