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

此生再无相见时 提交于 2019-11-26 20:46:59

问题


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 dialog.

I've tried to use WindowsFormsHost with RichTextBox box inside but that does not worked for me: NLog opened separate Windows Form anyway.


回答1:


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



回答2:


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


来源:https://stackoverflow.com/questions/3705480/how-can-i-use-nlogs-richtextbox-target-in-wpf-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!