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

如何将命令绑定到RichTextBox嵌套ScrollBar的Scroll事件?

问题分析

你当前的代码无效的核心原因是:你在FlowDocument的Paragraph中手动添加的ScrollBar和RichTextBox自带的滚动条完全无关。RichTextBox的滚动条是内置在它的ControlTemplate里的(对应模板中的PART_ContentHost,一个ScrollViewer控件),你手动添加的这个ScrollBar只是一个独立的UI元素,不会响应RichTextBox的滚动操作,所以绑定的命令自然不会触发。

RichTextBox 解决方案(MVVM+Interactivity)

要绑定RichTextBox内部滚动条的滚动事件到命令,最可靠的方式是自定义一个Behavior,通过它找到RichTextBox模板中的ScrollViewer,并订阅其ScrollChanged事件来触发命令:

1. 自定义 Behavior 类

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Input;

namespace YourNamespace
{
    public class RichTextBoxScrollBehavior : Behavior<RichTextBox>
    {
        public static readonly DependencyProperty ScrollCommandProperty =
            DependencyProperty.Register(
                nameof(ScrollCommand), 
                typeof(ICommand), 
                typeof(RichTextBoxScrollBehavior));

        public ICommand ScrollCommand
        {
            get => (ICommand)GetValue(ScrollCommandProperty);
            set => SetValue(ScrollCommandProperty, value);
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.TemplateApplied += OnTemplateApplied;
            if (AssociatedObject.Template != null)
                HookScrollViewer();
        }

        private void OnTemplateApplied(object sender, RoutedEventArgs e)
        {
            HookScrollViewer();
        }

        private void HookScrollViewer()
        {
            if (AssociatedObject.Template.FindName("PART_ContentHost", AssociatedObject) is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged += OnScrollChanged;
            }
        }

        private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ScrollCommand?.Execute(e);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            if (AssociatedObject.Template.FindName("PART_ContentHost", AssociatedObject) is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged -= OnScrollChanged;
            }
            AssociatedObject.TemplateApplied -= OnTemplateApplied;
        }
    }
}

2. XAML 中使用 Behavior

确保已引入Interactivity命名空间和自定义Behavior的命名空间:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:local="clr-namespace:YourNamespace"

然后修改RichTextBox的XAML:

<RichTextBox>
    <i:Interaction.Behaviors>
        <local:RichTextBoxScrollBehavior ScrollCommand="{Binding UpdateText}" />
    </i:Interaction.Behaviors>
    <RichTextBox.Document>
        <FlowDocument>
            <Paragraph>
                <Run Text="{Binding Text, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" />
            </Paragraph>
        </FlowDocument>
    </RichTextBox.Document>
</RichTextBox>
普通 TextBox 解决方案

普通TextBox的模板中同样包含名为PART_ContentHost的ScrollViewer,所以可以复用类似的思路,只需要将Behavior的泛型类型改为TextBox:

自定义 TextBoxScrollBehavior

using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
using System.Windows.Input;

namespace YourNamespace
{
    public class TextBoxScrollBehavior : Behavior<TextBox>
    {
        public static readonly DependencyProperty ScrollCommandProperty =
            DependencyProperty.Register(
                nameof(ScrollCommand), 
                typeof(ICommand), 
                typeof(TextBoxScrollBehavior));

        public ICommand ScrollCommand
        {
            get => (ICommand)GetValue(ScrollCommandProperty);
            set => SetValue(ScrollCommandProperty, value);
        }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.TemplateApplied += OnTemplateApplied;
            if (AssociatedObject.Template != null)
                HookScrollViewer();
        }

        private void OnTemplateApplied(object sender, RoutedEventArgs e)
        {
            HookScrollViewer();
        }

        private void HookScrollViewer()
        {
            if (AssociatedObject.Template.FindName("PART_ContentHost", AssociatedObject) is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged += OnScrollChanged;
            }
        }

        private void OnScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            ScrollCommand?.Execute(e);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            if (AssociatedObject.Template.FindName("PART_ContentHost", AssociatedObject) is ScrollViewer scrollViewer)
            {
                scrollViewer.ScrollChanged -= OnScrollChanged;
            }
            AssociatedObject.TemplateApplied -= OnTemplateApplied;
        }
    }
}

XAML 使用

<TextBox>
    <i:Interaction.Behaviors>
        <local:TextBoxScrollBehavior ScrollCommand="{Binding UpdateText}" />
    </i:Interaction.Behaviors>
    <TextBox.Text>
        <Binding Path="Text" Mode="TwoWay" UpdateSourceTrigger="LostFocus" />
    </TextBox.Text>
</TextBox>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:45:24