使用WPF的TextBox显示自定义日志
TextBox中显示各种日志,随滚动条的位置不同,日志显示需要有区别: 竖直滚动条在最下面时,最新日志添加到最末行,并显示最新日志;竖直滚动条不在最下面时,最新日志同样添加到最末行,但可视区域显示的日志始终不变化位置。
滚动条在最底端
上下两张图,滚动条在最下方,最末行更新显示最新日志
滚动条不在最底端
上下两张图,滚动条在变化,但可视区域显示内容没有变化
小二,上代码
1)MainWindow.xaml
<Window x:Class="LogText.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="日志文本框" Height="350" Width="200">
<Grid>
<TextBox Name="txtLog" AcceptsReturn="True"
TextWrapping="Wrap" Foreground="Green"
Grid.Row="1" Grid.ColumnSpan="2"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"/>
</Grid>
</Window>
2)MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
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 LogText
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ThreadPool.QueueUserWorkItem(sender =>
{
while (true)
{
this.txtLog.Dispatcher.BeginInvoke((Action)delegate
{
this.txtLog.AppendText(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss fff\r\n"));
if (IsVerticalScrollBarAtBottom)
{
this.txtLog.ScrollToEnd();
}
});
Thread.Sleep(600);
}
});
}
/// <summary>
/// 日志文本框滚动条是否在最下方
/// true:文本框竖直滚动条在文本框最下面时,可以在文本框后追加日志
/// false:当用户拖动文本框竖直滚动条,使其不在最下面时,即用户在查看旧日志,此时不添加新日志,
/// </summary>
public bool IsVerticalScrollBarAtBottom
{
get
{
bool atBottom = false;
this.txtLog.Dispatcher.Invoke((Action)delegate
{
//if (this.txtLog.VerticalScrollBarVisibility != ScrollBarVisibility.Visible)
//{
// atBottom= true;
// return;
//}
double dVer = this.txtLog.VerticalOffset; //获取竖直滚动条滚动位置
double dViewport = this.txtLog.ViewportHeight; //获取竖直可滚动内容高度
double dExtent = this.txtLog.ExtentHeight; //获取可视区域的高度
if (dVer + dViewport >= dExtent)
{
atBottom = true;
}
else
{
atBottom = false;
}
});
return atBottom;
}
}
}
}