繁体   English   中英

Winforms - 为隐藏按钮调用 Click() 事件

[英]Winforms - Invoke Click() event for hidden button

我创建了一个动态创建的表单菜单,并在单击父项后显示/隐藏子项。 我有一个代码可以检查BaseMenuForm上的键盘键。 当检测到快捷方式时,我需要为相关按钮执行单击事件。 我的问题是当子项不可见时PerformClick()事件不起作用。

我通过将事件分配给ShortcutAction属性找到了解决方法。 我认为没有必要两次分配相同的事件,但目前我不知道如何克服这个问题。 我不想显示快捷方式的所有菜单项。

如果配置了快捷方式,您可以看到“TODO”备注和执行解决方法的第二个构造函数。 当用户单击按钮时, Click事件按预期工作,因此它不能以编程方式工作。

这是我的代码的一部分(仅相关部分):

在设计器上设置了以下属性。 BaseMenuForm_KeyDown事件按预期调用。

BaseMenuForm.KeyPreview = true;

我的项目 class:

    /// <summary>
    /// The menu item settings.
    /// </summary>
    public class MyItem : Button
    {
        #region Properties

        /// <summary>
        /// The keyboard keys shortcut.
        /// </summary>
        public Shortcut Shortcut { get; }

        /// <summary>
        /// The action that will be called by the shortcut.
        /// TODO: why not working when I call PerformClick()
        /// </summary>
        public Action ShortcutAction { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes the item instance.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="text">The text.</param>
        /// <param name="onClickEvent">The event that will be triggered on cick.</param>
        public MyItem(string name, string text, EventHandler onClickEvent) : this(name, text)
        {
            if (onClickEvent == null)
            {
                throw new ArgumentNullException(nameof(onClickEvent));
            }
            else
            {
                Click += onClickEvent;
            }
        }

        /// <summary>
        /// Initializes the item instance.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="text">The text.</param>
        /// <param name="onClickEvent">The event that will be triggered on cick.</param>
        /// <param name="shortcut">The keyboard shortcut.</param>
        public MyItem(string name, string text, EventHandler onClickEvent, Shortcut shortcut) : this(name, text, onClickEvent)
        {
            ShortcutAction = () => onClickEvent(this, EventArgs.Empty); //TODO: Why do I need this?
            Shortcut = shortcut;
        }

        #endregion

        #region Methods

       
    }

BaseMenuForm:这个 class 包含表单,每个继承这个表单的表单都会有一个菜单。

        #region Shortcut

        private void BaseMenuForm_KeyDown(object sender, KeyEventArgs e)
        {
            CheckShortcut(e.KeyData);
        }

        /// <summary>
        /// Checks if the pressed keys is a shortcut combination.
        /// </summary>
        /// <param name="keyData">The keys.</param>
        private void CheckShortcut(Keys keyData)
        {
            var shortut = (Shortcut)keyData;
            Logger.LogDebug($"Got shortcut {shortut}");
            if(Shortcuts.TryGetValue(shortut, out var button) && button.ShortcutAction != null)
            {
                button.ShortcutAction();
                //button.PerformClick(); //TODO: why not working !
            }
            else
            {
                Logger.LogDebug("No click");
            }
        }

        #endregion

当您按下该键时,您的一个按钮将成为焦点。 它阻止父控件 (BaseMenuForm) 处理此事件。

使固定:

BaseMenuForm.KeyPreview = true;

我将回答以下问题:

  1. 为什么PerfromClick不适用于不可见的按钮?
  2. 这个问题的解决方法是什么?

对 1 的回答- 如果您查看PerfromClick 方法的源代码,您会看到第一条语句是一个检查: if (CanSelect)并且如果进一步遵循代码,您会看到CanSelect方法在控件未启用时返回 false 或不可见。 所以这就是原因。

对 2 的回答- 作为一种解决方法,您可以使用按钮的可访问 object 并调用基本上执行单击按钮的默认操作

button1.AccessibilityObject.DoDefaultAction();

或者作为另一种解决方法,使用反射来调用 OnClick 方法:

button1.GetType().GetMethod("OnClick", 
    System.Reflection.BindingFlags.NonPublic |
    System.Reflection.BindingFlags.Instance)
    .Invoke(button, new object[] { EventArgs.Empty });

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM