I read the following posts but neither helped to just get the same efficient way of printing logs from NLog onto a RichTextBox control target as in Winforms.
How can I use NLog's RichTextBox Target in WPF application?
WPF: Binding RichTextBox to Logger Output
I also browsed the official forum but with no success (except suggestions to read the two above posts).
The idea would be to add the target as:
<target xsi:type="RichTextBox" name="console"
layout="${longdate:useUTC=true}|${level:uppercase=true}|${logger}::${message}"
autoScroll="true"
maxLines="1000000"
controlName="rtbConsole"
formName="MyWPFWindowName"
useDefaultRowColoringRules="true">
</target>
And within the WPF window with MyWPFWindowName as name, to add a RichTextBox control with rtbConsole. Even if I create the target programmatically after the winow has been loaded, it will not use the existing rtbConsole but create a new form.
So, your help is appreciated!
I created a custom NLog target and linked it to a text box.
public class NlogMemoryTarget : Target
{
public Action<string> Log = delegate { };
public NlogMemoryTarget (string name, LogLevel level)
{
LogManager.Configuration.AddTarget (name, this);
LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", level, this));//This will ensure that exsiting rules are not overwritten
LogManager.Configuration.Reload(); //This is important statement to reload all applied settings
//SimpleConfigurator.ConfigureForTargetLogging (this, level); //use this if you are intending to use only NlogMemoryTarget rule
}
protected override void Write (AsyncLogEventInfo[] logEvents)
{
foreach (var logEvent in logEvents) {
Write (logEvent);
}
}
protected override void Write (AsyncLogEventInfo logEvent)
{
Write (logEvent.LogEvent);
}
protected override void Write (LogEventInfo logEvent)
{
Log (logEvent.FormattedMessage);
}
}
public partial class MainWindow
{
private NlogMemoryTarget _Target;
public MainWindow ()
{
InitializeComponent ();
this.Loaded += (s, e) => {
_Target = new NlogMemoryTarget ("text box output", LogLevel.Trace);
_Target.Log += log => LogText (log);
};
}
private void LogText (string message)
{
this.Dispatcher.Invoke ((Action) delegate () {
this.MessageView.AppendText (message + "\n");
this.MessageView.ScrollToEnd ();
});
}
}
While this not really answer your question, but i believe this solution is better. An wpf control used to show NLog logs in listview. https://github.com/erizet/NlogViewer.
As @mafu's answer suggests:
[Create] a custom
NLog
[memory]Target
and [link] it to aTextBox
.
This sample will 'link it' via event
and Event Handler delegates.
Type
public class NlogMemoryTarget : Target
{
public event EventHandler<string> OnLog;
public NlogMemoryTarget(string name, LogLevel level) : this(name, level, level) {}
public NlogMemoryTarget(string name, LogLevel minLevel, LogLevel maxLevel)
{
// important: we want LogManager.Configuration property assign behaviors \ magic to occur
// see: https://stackoverflow.com/a/3603571/1366179
var config = LogManager.Configuration;
// Add Target and Rule to their respective collections
config.AddTarget(name, this);
config.LoggingRules.Add(new LoggingRule("*", minLevel, maxLevel, this));
LogManager.Configuration = config;
}
[Obsolete]
protected override void Write(AsyncLogEventInfo[] logEvents)
{
foreach (var logEvent in logEvents) {
Write(logEvent.LogEvent);
}
}
protected override void Write(AsyncLogEventInfo logEvent)
{
Write(logEvent.LogEvent);
}
protected override void Write(LogEventInfo logEvent)
{
OnLog(this, logEvent.FormattedMessage);
}
// consider overriding WriteAsyncThreadSafe methods as well.
}
public partial class MainWindow
{
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
private NlogMemoryTarget _nlogMemoryTarget;
public MainWindow()
{
InitializeComponent();
_nlogMemoryTarget = new NlogMemoryTarget("TextBoxOutput", LogLevel.Trace);
_nlogMemoryTarget.OnLog += LogText;
}
private void LogText(object sender, string message)
{
this.MessageView.AppendText($"{message}\n");
this.MessageView.ScrollToEnd();
}
private void DoSomething() {
logger.Trace("DoSomething called!");
}
}
When you call on DoSomething
(or do logger.Trace
), your overloaded methods in your memory target will execute - which raises the event OnLog
. Since you assigned an event handler, LogText
, to OnLog
in the construction of MainWindow
, it will execute.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With