【问题标题】:Trace listener to write to a text box (WPF application)跟踪侦听器以写入文本框(WPF 应用程序)
【发布时间】:2010-11-26 05:34:14
【问题描述】:

对于我的 WPF 应用程序,我使用 TextWriterTraceListener 将日志记录到文本文件。如何将 Trace 输出也显示到文本框?

【问题讨论】:

    标签: c# wpf textbox trace listener


    【解决方案1】:

    我将它用于 C# winforms,应该可以轻松调整为 wpf

    public class MyTraceListener : TraceListener
    {
        private TextBoxBase output;
    
        public MyTraceListener(TextBoxBase output) {
            this.Name = "Trace";
            this.output = output;
        }
    
    
        public override void Write(string message) {
    
            Action append = delegate() {
                output.AppendText(string.Format("[{0}] ", DateTime.Now.ToString()));
                output.AppendText(message); 
            };
            if (output.InvokeRequired) {
                output.BeginInvoke(append);
            } else {
                append();
            }
    
        }
    
        public override void WriteLine(string message) {
            Write(message + Environment.NewLine);
        }
    }
    

    像这样使用它

    TraceListener debugListener = new MyTraceListener (theTextBox);
    Debug.Listeners.Add(debugListener);
    Trace.Listeners.Add(debugListener);
    

    记得 Trace/Debug.Listeners.Remove(debugListener);当你不再需要它时。

    【讨论】:

    • 你的意思是new *My*TraceListener(theTextBox)
    • wpf equivalent 是什么
    【解决方案2】:

    如何实现一个自定义 TraceListener,它只是将跟踪消息附加到一个字符串?然后将该字符串公开为属性,实现 INotifyPropertyChanged 并将 TextBox 控件数据绑定到该属性。

    类似这样的:

    public class MyTraceListener : TraceListener, INotifyPropertyChanged
    {
        private readonly StringBuilder builder;
    
        public MyTraceListener()
        {
            this.builder = new StringBuilder();
        }
    
        public string Trace
        {
            get { return this.builder.ToString(); }
        }
    
        public override void Write(string message)
        {
            this.builder.Append(message);
            this.OnPropertyChanged(new PropertyChangedEventArgs("Trace"));
        }
    
        public override void WriteLine(string message)
        {
            this.builder.AppendLine(message);
            this.OnPropertyChanged(new PropertyChangedEventArgs("Trace"));
        }
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
    
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }
    }
    

    您需要将此 TraceListener 添加到活动侦听器列表中:

    Trace.Listeners.Add(new MyTraceListener());
    

    【讨论】:

    • 请记住,这种方法不是线程安全的 - 如果您从 gui 线程以外的其他线程登录,请不要将其连接到 gui 控件
    • 将 TextBox 控件数据绑定到该属性?不是线程安全的吗?
    【解决方案3】:

    下面的代码是@Mark Seemann 的C#6.0 风格的代码。

    public class MyTraceListener : TraceListener, INotifyPropertyChanged
    {
        private readonly StringBuilder _builder;
    
        public MyTraceListener()
        {
            _builder = new StringBuilder();
        }
    
        public string Trace => _builder.ToString();
    
        public override void Write(string message)
        {
            _builder.Append(message);
            OnPropertyChanged(new PropertyChangedEventArgs("Trace"));
        }
    
        public override void WriteLine(string message)
        {
            _builder.AppendLine(message);
            OnPropertyChanged(new PropertyChangedEventArgs("Trace"));
        }
    
        #region INotifyPropertyChanged Members
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
    
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChanged?.Invoke(this, e);
        }
    }
    

    假设 MainViewModel 是 MainWindow.xaml 文件的根 DataContext。要以 MVVM 方式应用 MyTraceListener,请在 MainViewModel.cs 中编写以下代码。

    private string _traceOutput;
    private readonly MyTraceListener _trace = new MyTraceListener();
    
    // Constructor
    public MainViewModel() {
    
        // ...your viewmodel initialization code.
    
        // Add event handler in order to expose logs to MainViewModel.TraceOutput property.
        WeakEventManager<INotifyPropertyChanged, PropertyChangedEventArgs>.AddHandler(_trace, "PropertyChanged", traceOnPropertyChanged);
        Trace.Listeners.Add(_trace);
    }
    
    private void traceOnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Trace")
            TraceOutput = _trace.Trace;
    }
    
    public string TraceOutput
    {
        get { return _traceOutput; }
        set {
            _traceOutput = value;
            RaisePropertyChanged(); // This method is from Mvvm-light.
        }
    }
    

    在 MainWindow.xaml 中,将 TraceOutput 属性绑定到 TextBox。如果您希望 TextBox 连同累积的日志一起滚动到底部,请应用 TextChanged 事件。

    <TextBox x:Name="TextBoxLog" TextWrapping="Wrap" Text="{Binding TraceOutput}" VerticalScrollBarVisibility="Auto" AcceptsReturn="True" TextChanged="TextBoxLog_OnTextChanged" />
    

    在 XAML 文件 (MainWindow.xaml.cs) 的代码隐藏中,事件处理程序如下所示。

        private void TextBoxLog_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            TextBoxLog.ScrollToEnd();
        }
    

    【讨论】:

      【解决方案4】:

      您可以附加一个自定义侦听器来更新 Textbox.Text 属性。 因此,您需要从抽象基类 TraceListener 继承并覆盖 TraaceData、TraceEvent、TraceTransfer 方法之一。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-09-24
        • 1970-01-01
        • 1970-01-01
        • 2013-04-15
        • 2015-02-25
        相关资源
        最近更新 更多