2009-09-07 67 views

回答

18

我用这个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); 

记住跟踪/ Debug.Listeners.Remove(debugListener);当你不再需要它时。

+0

BeginInvoke()的+1。常规调用()会挂起整个应用程序。 – sharkin 2009-10-07 19:50:42

+0

你的意思是'new * My * TraceListener(theTextBox)' – 2010-01-21 16:31:32

+0

什么是'wpf等效' – 2016-07-12 10:02:17

0

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

11

如何实现一个自定义的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()); 
+0

谢谢你,这似乎是一个非常好的主意。我希望得到一些指导。 – kjv 2009-09-07 12:56:19

+1

只要记住,这种方法不是线程安全的 - 不要挂钩到gui控件,如果你从其他线程登录而不是gui线程 – nos 2009-09-07 13:05:43

+0

@nos:好点。我将其作为练习留给读者:) – 2009-09-07 13:27:30

2

下面的代码是@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属性为文本框。如果您希望文本框随累积日志一起滚动到底部,请应用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(); 
    }