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 WindowsFo开发者_如何学JAVArmsHost with RichTextBox box inside but that does not worked for me: NLog opened separate Windows Form anyway.
A workaround in the mean time is to use the 3 classes available here, then follow this procedure:
Import the 3 files into your project
If not already the case, use
Project > Add Reference
to add references to the WPF assemblies:WindowsBase, PresentationCore, PresentationFramework
.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); }
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);
}
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);
精彩评论