TextBox中Windows窗体滚动日志输出的最佳方法

Ser*_*ver 30 .net logging textbox winforms

在Forms应用程序中,我正在显示生成大量输出的长时间运行的命令行应用程序的日志输出.我在后台启动程序,捕获其输出,并使用AppendText将其显示在TextBox中.我更喜欢只显示例如最后1000行.从TextBox中删除行是很昂贵的,而TextBox实际上并不是滚动日志显示的最佳方法.

关于在Windows窗体中执行滚动日志窗口的最佳控件的任何想法?

lig*_*t78 16

我以前有列表框做这种事情.如果行数达到1000,您只需删除第一行.如果日志行太长,您可以使列表框更宽一些(取决于日志信息以及是否可以从第一个可见的捕获含义)没有水平滚动的单词)并使水平滚动条可见.


Ser*_*ver 11

正是我需要的.我用下面的代码解决了这个问题,它保留了最后添加的项目:

    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();
         }
     }
Run Code Online (Sandbox Code Playgroud)

  • 作为一般规则,对于滚动日志,我喜欢将最新的项目保留在顶部.如果用户在列表框顶部看到一条突然消失的明显静态行,则可能会感到困惑. (2认同)

小智 7

有同样的需求,并赞赏了很多这方面的帮助.这是一个略微修改的版本.

创建一个列表框:

<ListBox x:Name="lbLog" Background="LightGray"></ListBox>
Run Code Online (Sandbox Code Playgroud)

在主线程中(在代码的初始部分),将其存储为存储对UI线程的引用:

Thread m_UIThread;
....
m_UIThread = Thread.CurrentThread;
Run Code Online (Sandbox Code Playgroud)

那么这是你的日志方法,可以从任何线程调用:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)