项目背景:wpf+prism
问题:在使用了mvvm模式的时候,当使用TextBox来作为界面日志显示的控件的时候,TextBox中的Text属性,在添加了新的日志信息之后,控件无法自动滚动到最新一行。由于使用了mvvm模式,也无法直接调用TextBox.ScrollToEnd()方法
解决方法:
提示:我的界面有多个View,对应的也有多个ViewModel,需要确定好当前的View和ViewModel。
- 在你的 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();
}
- 修改 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();
}
}
- 在 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中添加
- 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 到最后一行。