2009-09-07 68 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(); 
    }