项目背景:wpf+prism
问题:在使用了mvvm模式的时候,当使用TextBox来作为界面日志显示的控件的时候,TextBox中的Text属性,在添加了新的日志信息之后,控件无法自动滚动到最新一行。由于使用了mvvm模式,也无法直接调用TextBox.ScrollToEnd()方法

解决方法
提示:我的界面有多个View,对应的也有多个ViewModel,需要确定好当前的View和ViewModel。

  1. 在你的 View(通常是 MainWindow.xaml.cs,而我的是IndexView.xaml.cs)中,添加一个名为 LogTextBox 的公共属性,并在 XAML 中绑定该属性到 TextBox 控件:
    logTextBox_RemoteUpdate是xaml界面中展示日志的TextBox控件的x:Name
点击查看代码
public TextBox UpdateLogTextBox { get; set; }

public IndexView()
{
    InitializeComponent();

    Loaded += IndexView_Loaded;
}

private void IndexView_Loaded(object sender, RoutedEventArgs e)
{
    UpdateLogTextBox = FindName("logTextBox_RemoteUpdate") as TextBox;
    if (DataContext is IndexViewModel viewModel)
    {
        viewModel.ScrollToEndRequested += ScrollToEnd;
    }
}

private void ScrollToEnd()
{
    UpdateLogTextBox?.ScrollToEnd();
}
  1. 修改 ViewModel 中的 ScrollToEndCommand 命令,以便通过事件或委托将滚动操作传递到 View:
点击查看代码
public class IndexViewModel
{
    public ICommand ScrollToEndCommand { get; }

    public event Action ScrollToEndRequested;

    public IndexViewModel()
    {
        ScrollToEndCommand = new ActionCommand(ScrollToEnd);
    }

    private void ScrollToEnd()
    {
        ScrollToEndRequested?.Invoke();
    }
}
  1. 在 View(IndexWindow.xaml)中,使用行为来捕获 ViewModel 中的滚动请求,并执行滚动操作:
点击查看代码
<TextBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="TextChanged">
            <i:InvokeCommandAction Command="{Binding ScrollToEndCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

这一步用到了Behavior,需要安装Microsoft.Xaml.Behaviors.Wpf,nuget下载并在IndexWindow.xaml中添加

  1. IndexView.xaml.cs中的代码为
点击查看代码
public partial class IndexView : Window
{
    public TextBox LogTextBox { get; set; }

    public IndexView()
    {
        InitializeComponent();

        // 在窗口加载完成后,将 TextBox 控件实例赋值给 logTextBox_RemoteUpdate 属性
        Loaded += (sender, e) =>
        {
            LogTextBox = FindName("logTextBox_RemoteUpdate") as TextBox;
            if (DataContext is IndexViewModel viewModel)
            {
                viewModel.ScrollToEndRequested += ScrollToEnd;
            }
        };
    }

    private void ScrollToEnd()
    {
        LogTextBox?.ScrollToEnd();
    }
}

这样,通过在 View 中将 TextBox 控件的实例赋值给 LogTextBox 属性,并使用事件或委托将滚动请求传递到 View,你应该能够在 ViewModel 中触发滚动操作并成功滚动 TextBox 到最后一行。