2009-09-07 5 views

답변

18

나는

을 WPF에 쉽게 조절해야한다, C#을 윈폼이를 사용
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);를 기억하십시오. 더 이상 필요하지 않을 때.

+0

BeginInvoke(). 일반 Invoke()는 전체 앱을 정지시킵니다. – sharkin

+0

'new * My * TraceListener (theTextBox)'를 의미합니다 –

+0

무엇이'wpf equivalent '입니까? –

0

Textbox.Text 속성을 업데이트하는 사용자 지정 수신기를 추가 할 수 있습니다. 따라서 추상 기본 클래스 TraceListener에서 상속하고 TraaceData, 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

+1

이 방법은 스레드로부터 안전하지 않다는 것을 기억하십시오. gui 스레드가 아닌 다른 스레드에서 로깅하는 경우 GUI 컨트롤에 연결하지 마십시오. – nos

+0

@nos : 좋은 지적입니다. 나는 독자에게 운동으로 그것을 떠났다 : –

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이라고 가정합니다. MyTraceListener을 MVVM 방식으로 적용하려면 아래 코드를 MainViewModel.cs에 작성하십시오. MainWindow.xaml에서
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. 
    } 
} 

, 텍스트 상자에 TraceOutput 속성을 바인딩합니다. TextBox가 누적 된 로그와 함께 아래로 스크롤되도록하려면 TextChanged 이벤트를 적용하십시오.

XAML 파일 (MainWindow.xaml.cs를)의 코드 숨김에서
<TextBox x:Name="TextBoxLog" TextWrapping="Wrap" Text="{Binding TraceOutput}" VerticalScrollBarVisibility="Auto" AcceptsReturn="True" TextChanged="TextBoxLog_OnTextChanged" /> 

는 이벤트 핸들러는 단순히 다음과 같습니다.

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