【问题标题】:How can I use a RichTextBox as a NLog Target in a WPF application?如何在 WPF 应用程序中使用 RichTextBox 作为 NLog 目标?
【发布时间】:2011-07-07 22:04:34
【问题描述】:

我阅读了以下帖子,但都没有帮助获得与 Winforms 中相同的将日志从 NLog 打印到 RichTextBox 控件目标的有效方式。

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

WPF: Binding RichTextBox to Logger Output

我也浏览了官方论坛,但没有成功(除了建议阅读以上两个帖子)。

我们的想法是将目标添加为:

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

并在以 MyWPFWindowName 为名称的 WPF 窗口内,使用 rtbConsole 添加 RichTextBox 控件。即使我在加载 winow 后以编程方式创建目标,它也不会使用现有的 rtbConsole,而是创建一个新表单。

因此,感谢您的帮助!

【问题讨论】:

  • 到目前为止您尝试了哪些方法,结果如何?请显示一些代码,而不是简单地说不起作用。
  • 您在登录到 RichTextBox 时遇到了哪些具体问题? “效率不高”是相当模糊的。你期望发生什么?
  • 请看我上面的编辑。如果你使用 NLog 和 WPF,这个问题很容易复制。
  • 对于那些质疑问题是否有效的人,nlog richtextbox output to winforms richtextbox ONLY 并且这个问题询问了如何输出nlog ot wpf Richtextbox。我一直想做同样的事情但没有成功。

标签: .net wpf richtextbox target nlog


【解决方案1】:

我创建了一个自定义 NLog 目标并将其链接到一个文本框。

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

【讨论】:

  • @publicENEMY 已修复。在这种情况下,日志由委托发送到文本框。
  • @publicENEMY 不,这会绕过整个 NLog。相反,像往常一样在 NLog 中执行日志记录:private static _L = LogManager.GetCurrentClassLogger(); [...] _L.Info ("hello world");。您必须配置 _L 才能登录到在答案代码中创建的 MemoryTarget,请参见此处:stackoverflow.com/q/3516242/39590
  • 现在看来,对于一项简单的工作来说,这似乎需要做很多工作。我猜那是因为目标在 NLog 提供的默认集中不存在;(
  • 正是我想要的。谢谢。
  • @mafu SimpleConfigurator.ConfigureForTargetLogging (this, level); 覆盖所有日志记录配置。如果您已经配置了一些日志记录,则应该改用LogManager.Configuration.Reload();。也不要忘记LogManager.Configuration.LoggingRules.Add(new LoggingRule("*", level, this));,以便使用现有规则。
【解决方案2】:

虽然这并不能真正回答您的问题,但我相信这个解决方案更好。用于在列表视图中显示 NLog 日志的 wpf 控件。 https://github.com/erizet/NlogViewer.

【讨论】:

    【解决方案3】:

    正如@mafu 的回答所暗示的:

    [创建] 自定义 NLog [内存] Target 并将其[链接] 到 TextBox

    此示例将通过event 和事件处理程序委托“链接”它。

    将 NLog 内存目标定义为 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.
    }
    

    在 WPF 窗口控件中的使用

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

    当您调用DoSomething(或执行logger.Trace)时,您的内存目标中的重载方法将执行 - 这会引发事件OnLog。由于您在MainWindow 的构造中将事件处理程序LogText 分配给OnLog,因此它将执行。

    【讨论】:

      【解决方案4】:

      我同意问题中引用的 2 个链接不是最佳的。 (我也不会使用这些解决方案。)

      这是我要尝试的:

      Write a custom (WPF) control target 使用类似于 NLog 的FormControlTarget 的算法。

      Ensure to register your new target.
      此外,NLog 的FormHelper 可能会有所帮助。

      大部分 WinForms 代码应该可以轻松转换为 WPF。

      【讨论】:

        猜你喜欢
        • 2011-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-02
        • 2015-10-23
        • 1970-01-01
        • 1970-01-01
        • 2012-08-07
        相关资源
        最近更新 更多