【WPF实现RichTextBox添加文本、自动滚动】

前言

使用WPF 中的RichTextBox控件实现添加文本后自动滚动末尾。因为RichTextBox无法直接绑定数据,所以通过引用System.Windows.Interactivity实现(System.Windows.Interactivity.WPF)

代码

MainWindow.xaml

csharp 复制代码
<Window x:Class="WPF_MvvmDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:behavior="clr-namespace:WPF_MvvmDemo" 
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <RichTextBox Name="OutputListBox" Grid.Row="0"  
                     Margin="5" Background="#FFFFFF" Focusable="True" 
                     VerticalScrollBarVisibility="Auto">
            <!--数据绑定-->
            <i:Interaction.Behaviors>
                <behavior:RichTextBoxBehavior Document="{Binding RichTextContent, Mode=TwoWay}" />
            </i:Interaction.Behaviors>
            <!--自动滚动-->
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="TextChanged">
                    <ei:CallMethodAction MethodName="ScrollToEnd" />
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </RichTextBox>
       
        <Button  Grid.Row="2" Width="150" Margin="5" HorizontalAlignment="Right"
                 Command="{Binding AppendTextCommand}">AddText</Button>
    </Grid>
</Window>

MainWindow

csharp 复制代码
public partial class MainWindow : Window
{
    MainViewModel viewModel;
    public MainWindow()
    {
        InitializeComponent();
        viewModel=new MainViewModel();
        this.DataContext = viewModel;
    }
}

RelayCommand

csharp 复制代码
public class RelayCommand : ICommand
{
    public Action<string> execute;

    public RelayCommand(Action<string> execute)
    {
        this.execute = execute;
    }

    public event EventHandler? CanExecuteChanged;

    public bool CanExecute(object? parameter)
    {
        return CanExecuteChanged!=null;
    }

    public void Execute(object? parameter)
    {
        execute?.Invoke(parameter?.ToString());
    }
}

RichTextBoxBehavior

csharp 复制代码
/// <summary>
///RichTextBox 的 Document 属性不是一个依赖属性(DependencyProperty),因此不能直接进行双向数据绑定。
///我们需要使用一种间接的方式来实现数据绑定。
///解决方案:
///使用 Behavior 来实现 RichTextBox 的数据绑定。Behavior 是一个附加行为,可以在 XAML 中使用,
///通过代码来实现复杂的行为逻辑。
/// </summary>
public class RichTextBoxBehavior : Behavior<RichTextBox>
{
    public static readonly DependencyProperty DocumentProperty =
        DependencyProperty.Register("Document", typeof(FlowDocument), typeof(RichTextBoxBehavior),
            new FrameworkPropertyMetadata(null, OnDocumentChanged));

    public FlowDocument Document
    {
        get { return (FlowDocument)GetValue(DocumentProperty); }
        set { SetValue(DocumentProperty, value); }
    }

    private static void OnDocumentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behavior = d as RichTextBoxBehavior;
        if (behavior != null)
        {
            behavior.UpdateRichTextBox((FlowDocument)e.NewValue);
        }
    }

    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += OnLoaded;
        AssociatedObject.TextChanged += OnTextChanged;
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.Loaded -= OnLoaded;
        AssociatedObject.TextChanged -= OnTextChanged;
    }

    private void OnLoaded(object sender, RoutedEventArgs e)
    {
        UpdateRichTextBox(Document);
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        Document = AssociatedObject.Document;
    }

    private void UpdateRichTextBox(FlowDocument document)
    {
        if (document != null && AssociatedObject.Document != document)
        {
            AssociatedObject.Document = document;
        }
    }
}

运行结果

相关推荐
明耀10 小时前
WPF DataGrid 默认显示行号
wpf
lph197214 小时前
wpf的converter
wpf
fyifei055814 小时前
WPF学习PropertyChanged
wpf
爱炸薯条的小朋友14 小时前
C#由于获取WPF窗口名称造成的异常报错问题
windows·c#·wpf
baivfhpwxf202315 小时前
wpf ListBox 去除item 单击样式
wpf
诗仙&李白15 小时前
lnnovationHubTool,用prism+WPF编写的MVVM模式的快速上位机软件开发框架平台
wpf·mvvm·prism·上位机软件开发框架平台
程序员小刘19 小时前
【HarmonyOS 5】教育开发实践详解以及详细代码案例
华为·wpf·harmonyos
Java Fans1 天前
在WPF项目中集成Python:Python.NET深度实战指南
python·.net·wpf
布伦鸽2 天前
C# WPF 左右布局实现学习笔记(1)
笔记·学习·c#·wpf
code bean3 天前
【WPF】WPF 项目实战:构建一个可增删、排序的光源类型管理界面(含源码)
wpf