Log all button clicks in Win Forms app

2019-06-03 03:30发布

I'm looking to add a log statement for every WinForms button click that the user clicks, and ideally, an indentifier of the parent form (such as the title bar). I have seen posts logging all mouse clicks, but i'm interested in just logging button clicks. I have read the accepted answer here and adapted it:

    public class ButtonLogger
    {
        private static readonly ILog Logger = LogManager.GetLogger(typeof(ButtonLogger));

        public static void AttachButtonLogging(Control.ControlCollection controls)
        {
            foreach (var button in controls.OfType<Button>())
            {
                button.Click += LogButtonClick;
            }
        }

        private static void LogButtonClick(object sender, EventArgs eventArgs)
        {

            Button button = sender as Button;
            Logger.InfoFormat("Button clicked: {0} ({1})", button.Text, button.Parent.Text);
        }
    }

This class is used at the end of a constructor in a form, e.g. :

ButtonLogger.AttachButtonLogging(this.Controls);

The problem I'm facing with this is that the Controls property doesn't seem to have a reference to my buttons. Presumably this is because the buttons aren't added directly to the form, but rather, another control that is in the Controls property. However, the Controls property only contains a single control, a ToolStrip.

Is there a way I can harness all of the buttons on a form, regardless of their parent container? My final goal is to add a log statement to my buttons, so if this can be accomplished some other way besides button click event methods, then I'm open to that as well

2条回答
2楼-- · 2019-06-03 04:18

I believe you need to search for buttons recursively:

public static void AttachButtonLogging(Control.ControlCollection controls)
{
    foreach (var control in controls.Cast<Control>())
    {
        if (control is Button)
        {
           Button button = (Button)control;
           button.Click += LogButtonClick;
        }
        else
        {
            AttachButtonLogging(control.Controls);
        }
    }
}
查看更多
一夜七次
3楼-- · 2019-06-03 04:20

One thing you could consider is to create a subclass of the standard Button class, and let the buttons themselves do the logging. Of course, you'd have to go around and substitute all the buttons in the application for your own implementation, but it should be possible to do that with a global search+replace.

Here's an example implementation:

public class LoggerButton : Button
{
    private static readonly ILog Logger = LogManager.GetLogger(typeof(LoggerButton));

    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        Logger.InfoFormat("Button clicked: {0} ({1})", this.Text, this.Parent.Text);
    }
}
查看更多
登录 后发表回答