2009-09-07 11 views

Respuesta

18

lo uso para C# WinForms, debe ser fácilmente ajustable a 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); 
    } 
} 

Úselo como

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

Recuerde Trace/Debug.Listeners.Remove (debugListener); cuando ya no lo necesites

+0

+1 para BeginInvoke(). Invoke regular() bloquea la aplicación completa. – sharkin

+0

Quieres decir 'new * My * TraceListener (theTextBox)' –

+0

¿cuál es el 'equivalente wpf' –

0

puede agregar un Oyente personalizado que actualice la propiedad Textbox.Text. Por lo tanto, debe heredar de la clase base abstracta TraceListener y anular uno de los métodos TraaceData, TraceEvent, TraceTransfer.

11

¿Qué le parece implementar un TraceListener personalizado que simplemente anexa mensajes de rastreo a una cadena? A continuación, expone esa cadena como una propiedad, implementa INotifyPropertyChanged y da un control de TextBox a esa propiedad.

Algo como esto:

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); 
     } 
    } 
} 

que tendría que añadir este TraceListener a la lista de oyentes activos:

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

Gracias, parece una muy buena idea. Agradecería alguna guía. – kjv

+1

Solo recuerde que este enfoque no es seguro para subprocesos: no lo conecte a los controles gui si está registrando desde otros subprocesos que el subproceso gui – nos

+0

@nos: Buen punto. Lo dejé como un ejercicio para el lector :) –

2

El siguiente código es el estilo C# 6.0 del código de @Mark Seemann.

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); 
    } 
} 

Supóngase que es root MainViewModel DataContext de archivo MainWindow.xaml. Para aplicar MyTraceListener de manera MVVM, escriba el código siguiente en 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. 
    } 
} 

En MainWindow.xaml, unir TraceOutput propiedad de cuadro de texto. Si desea que TextBox se desplace hacia abajo junto con los registros acumulados, aplique el evento TextChanged.

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

de código subyacente de archivo XAML (MainWindow.xaml.cs), controlador de eventos es simplemente de la siguiente manera.

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