How can I use NLog's RichTextBox Target in WPF application?

前端 未结 2 1522
春和景丽
春和景丽 2020-12-05 22:42

How can I use RichTextBox Target in WPF application? I don\'t want to have a separate window with log, I want all log messages to be outputted in richTextBox located in WPF

相关标签:
2条回答
  • 2020-12-05 22:59

    If you define a RichTextBoxTarget in the config file, a new form is automatically created. This is because NLog initializes before your (named) form and control has been created. Even if you haven't got any rules pointing to the target. Perhaps there is a better solution, but I solved it by creating the target programatically:

    using NLog;
    //[...]
    RichTextBoxTarget target = new RichTextBoxTarget();
    target.Name = "RichTextBox";
    target.Layout = "${longdate} ${level:uppercase=true} ${logger} ${message}";
    target.ControlName = "textbox1";
    target.FormName = "Form1";
    target.AutoScroll = true;
    target.MaxLines = 10000;
    target.UseDefaultRowColoringRules = false;
    target.RowColoringRules.Add(
        new RichTextBoxRowColoringRule(
            "level == LogLevel.Trace", // condition
            "DarkGray", // font color
            "Control", // background color
            FontStyle.Regular
        )
    );
    target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Debug", "Gray", "Control"));
    target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Info", "ControlText", "Control"));
    target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Warn", "DarkRed", "Control"));
    target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Error", "White", "DarkRed", FontStyle.Bold));
    target.RowColoringRules.Add(new RichTextBoxRowColoringRule("level == LogLevel.Fatal", "Yellow", "DarkRed", FontStyle.Bold));
    
    AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
    asyncWrapper.Name = "AsyncRichTextBox";
    asyncWrapper.WrappedTarget = target;
    
    SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);
    
    0 讨论(0)
  • 2020-12-05 23:01

    A workaround in the mean time is to use the 3 classes available here, then follow this procedure:

    1. Import the 3 files into your project

    2. If not already the case, use Project > Add Reference to add references to the WPF assemblies: WindowsBase, PresentationCore, PresentationFramework.

    3. In WpfRichTextBoxTarget.cs, replace lines 188-203 with:

          //this.TargetRichTextBox.Invoke(new DelSendTheMessageToRichTextBox(this.SendTheMessageToRichTextBox), new object[] { logMessage, matchingRule });
          if (System.Windows.Application.Current.Dispatcher.CheckAccess() == false) {
              System.Windows.Application.Current.Dispatcher.Invoke(new Action(() => {
                  SendTheMessageToRichTextBox(logMessage, matchingRule);
              }));
          }
          else {
              SendTheMessageToRichTextBox(logMessage, matchingRule);
          }
      }
      
      private static Color GetColorFromString(string color, Brush defaultColor) {
          if (defaultColor == null) return Color.FromRgb(255, 255, 255); // This will set default background colour to white.
          if (color == "Empty") {
              return (Color)colorConverter.ConvertFrom(defaultColor);
          }
      
          return (Color)colorConverter.ConvertFromString(color);
      }
      
    4. In your code, configure the new target like this below example:

    I hope it helps, but it definitely does not seem to be a comprehensive implementation...

    public void loading() {
        var target = new WpfRichTextBoxTarget();
        target.Name = "console";
        target.Layout = "${longdate:useUTC=true}|${level:uppercase=true}|${logger}::${message}";
        target.ControlName = "rtbConsole"; // Name of the richtextbox control already on your window
        target.FormName = "MonitorWindow"; // Name of your window where there is the richtextbox, but it seems it will not really be taken into account, the application mainwindow will be used instead.
        target.AutoScroll = true;
        target.MaxLines = 100000;
        target.UseDefaultRowColoringRules = true;
        AsyncTargetWrapper asyncWrapper = new AsyncTargetWrapper();
        asyncWrapper.Name = "console";
        asyncWrapper.WrappedTarget = target;
        SimpleConfigurator.ConfigureForTargetLogging(asyncWrapper, LogLevel.Trace);
    }
    
    0 讨论(0)
提交回复
热议问题