.net 在 TextBox 中 Windows 窗体滚动日志输出的最佳方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/383813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best approach to Windows Forms rolling log output in TextBox
提问by Serge van den Oever
In a Forms application I'm displaying log output from a long running command-line application that generated a lot of output. I start the program in the background, and capture its output and currently display it in a TextBox using AppendText. I prefer to only display for example the last 1000 lines. Removing lines from a TextBox is expensive, and a TextBox does not really feels like the best approach for rolling log display.
在 Forms 应用程序中,我显示了一个长时间运行的命令行应用程序的日志输出,该应用程序生成了大量输出。我在后台启动程序,捕获它的输出并当前使用 AppendText 在 TextBox 中显示它。我更喜欢只显示例如最后 1000 行。从 TextBox 中删除行的成本很高,而且 TextBox 并不是滚动日志显示的最佳方法。
Any ideas on the best Control to do a rolling log window in Windows Forms?
关于在 Windows 窗体中执行滚动日志窗口的最佳控件的任何想法?
采纳答案by liggett78
I used to have listboxes do this kind of thing. You just remove the first line if the line count reaches, say, 1000. If the log line is too long, you could make the listbox a bit wider (depends on the log information and whether it's possible to catch the meaning from the first visible words without horizontal scrolling) and make the horizonal scrollbar visible.
我曾经让列表框做这种事情。如果行数达到,例如 1000,您只需删除第一行。如果日志行太长,您可以使列表框更宽一些(取决于日志信息以及是否可以从第一个可见的地方捕捉含义没有水平滚动的单词)并使水平滚动条可见。
回答by Serge van den Oever
exactly what I needed. I solved it with the following code which keeps the last added item visible:
正是我所需要的。我使用以下代码解决了它,该代码使最后添加的项目保持可见:
delegate void UpdateCCNetWindowDelegate(String msg);
private void Message2CCNetOutput(String message)
{
// Check whether the caller must call an invoke method when making method calls to listBoxCCNetOutput because the caller is
// on a different thread than the one the listBoxCCNetOutput control was created on.
if (listBoxCCNetOutput.InvokeRequired)
{
UpdateCCNetWindowDelegate update = new UpdateCCNetWindowDelegate(Message2CCNetOutput);
listBoxCCNetOutput.Invoke(update, message);
}
else
{
listBoxCCNetOutput.Items.Add(message);
if (listBoxCCNetOutput.Items.Count > Program.MaxCCNetOutputLines)
{
listBoxCCNetOutput.Items.RemoveAt(0); // remove first line
}
// Make sure the last item is made visible
listBoxCCNetOutput.SelectedIndex = listBoxCCNetOutput.Items.Count - 1;
listBoxCCNetOutput.ClearSelected();
}
}
回答by Serge van den Oever
Had the same need and appreciated a lot this help. This is a slightly modified version.
有同样的需求并非常感谢这种帮助。这是一个稍微修改的版本。
Create a listbox:
创建一个列表框:
<ListBox x:Name="lbLog" Background="LightGray"></ListBox>
In the main thread (in the intial part of the code),put this to store a reference to the UI thread:
在主线程中(在代码的初始部分),将其用于存储对 UI 线程的引用:
Thread m_UIThread;
....
m_UIThread = Thread.CurrentThread;
Then this is your log method, callable from any thread:
然后这是您的日志方法,可从任何线程调用:
public void AddToLog(String message)
{
if (Thread.CurrentThread != m_UIThread)
{
// Need for invoke if called from a different thread
this.Dispatcher.BeginInvoke(
DispatcherPriority.Normal, (ThreadStart)delegate()
{
AddToLog(message);
});
}
else
{
// add this line at the top of the log
lbLog.Items.Insert(0, message);
// keep only a few lines in the log
while (lbLog.Items.Count > LOG_MAX_LINES)
{
lbLog.Items.RemoveAt(lbLog.Items.Count-1);
}
}
}
回答by Introdur
very simple solution
非常简单的解决方案
Textbox1.Appendtext(<yourtext>)
for rolling log like console
用于像控制台一样滚动日志
回答by Introdur
I needed to do this a while ago and the Listbox was the solution. No one will even notice the difference.
不久前我需要这样做,而列表框就是解决方案。甚至没有人会注意到其中的差异。

