【问题标题】:How to enable a WinForm button in time to receive focus by tabbing如何通过 Tab 及时启用 WinForm 按钮以接收焦点
【发布时间】:2012-08-10 03:52:13
【问题描述】:

Visual Studio 2010,C#

我有一个ComboBox,其中一个DropDownAutoComplete 设置为SuggestAppend,而AutoCompleteSource 来自ListItems。用户将数据键入其中,直到输入正确为止。在数据与列表项之一匹配之前,组合框旁边的按钮将被禁用。

如果用户点击 tab 键,自动完成功能会接受当前的建议。它还移动到启用的选项卡序列中的下一个控件。当然,因为我希望它转到禁用按钮,所以我需要在验证条目后立即启用它。

问题是我尝试过的所有事件PreviewKeyDownLostFocusSelectedIndexChanged 都不允许我及时启用按钮以使其被处理并获得焦点。它总是按 Tab 键顺序转到下一个按钮,该按钮始终处于启用状态。

我已经准备好让按钮保持启用状态,如果过早按下它会报错,但我不想那样做。我也不想使用特殊模式标志来跟踪这些控件何时获得焦点。验证似乎是正常的事情,但我被卡住了。

如果SelectedIndexChanged 在用户进行匹配时有效,这将很容易。当框清除或找到键入的匹配项时,它不会触发。

【问题讨论】:

    标签: c# winforms events windows-controls


    【解决方案1】:

    您可以创建自己的 ComboBox 类来封装此行为。像这样的:

    using System;
    using System.Windows.Forms;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                this.myComboBox1.TheButton = this.button1;
    
                this.myComboBox1.Items.AddRange( new string[] {
                    "Monday",
                    "Tuesday",
                    "Wednesday",
                    "Thursday",
                    "Friday",
                    "Saturday",
                    "Sunday"
                } );
    
                button1.Enabled = false;
            }
        }
    
        public class MyComboBox : ComboBox
        {
            public Control TheButton { get; set; }
    
            public MyComboBox()
            {
            }
    
            bool IsValidItemSelected
            {
                get { return null != this.SelectedItem; }
            }
    
            protected override void OnValidated( EventArgs e )
            {
                if ( null != TheButton )
                {
                    TheButton.Enabled = this.IsValidItemSelected;
                    TheButton.Focus();
                }
    
                base.OnValidated( e );
            }
    
            protected override void OnTextChanged( EventArgs e )
            {
                if ( null != TheButton )
                {
                    TheButton.Enabled = this.IsValidItemSelected;
                }
    
                base.OnTextChanged( e );
            }
        }
    }
    

    【讨论】:

    • 感谢您抽出宝贵时间创建此内容。一个问题是按钮焦点是在 OnValidated 事件中设置的。 VS2010 帮助声明“不要尝试从 Enter、GotFocus、Leave、LostFocus、Validating 或 Validated 事件处理程序中设置焦点。这样做会导致您的应用程序或操作系统停止响应。”其次,验证事件发生在 Leave 事件之后,这也太晚了,所以看起来我不能做我想做的事情。
    • “所以看起来我无法为所欲为。”我在答案中创建的测试应用程序可以满足您的需求。你试过了吗?
    • 不,我没有,因为谨慎似乎非常具体。它确实有效。多一点 tweeking 它将在用户完成输入后立即启用该按钮。我确实有另一个使用不违反警告的 ProcessCmdKey 表单覆盖的解决方案。我可能是字面意思,但在过去 15 年与 Delphi 一起使用 Win32 工作后,我是 .Net 的新手,并且有足够的差异,我很谨慎。
    【解决方案2】:
    try this :
    

    key_press 事件:

    if (e.KeyData == Keys.Enter)
            {
                button2.Enabled = true;
                button2.Focus();
            }
    

    【讨论】:

    • 这对 Tab 键不起作用。 KeyPress 事件也不提供 KeyData。
    【解决方案3】:

    使用组合框的“Validated”事件来设置按钮的启用状态,而不是您提到的事件处理程序(LostFocus、SelectedIndexChanged 和 PreviewKeyDown)。

    您可能还需要手动将焦点放在按钮上以强制焦点移动到该按钮上。

    例如

        private void comboBox1_Validated(object sender, EventArgs e)
        {
            button1.Enabled = true;
            button1.Focus();
        }
    

    【讨论】:

    • 在验证中分配焦点假设太多。假设它会留在那里,如果用户单击表单上的另一个按钮怎么办?它也在帮助中被警告。请参阅我对 ahazzah 的评论。
    • 这是一个公平的选择。我误解了“我希望它转到禁用按钮”的意思。重新阅读后,很明显你的意思是,如果用户点击 tab 键,你想要那种行为。
    【解决方案4】:

    考虑到这里的其他答案,我想出了一个不使用 AutoComplete 的部分场景。副作用是 PreviewKeyDown 事件被第二次调用,因此验证被调用了两次。我想知道为什么...也许我应该问另一个问题。

        private void comboBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
          if (e.KeyData == Keys.Tab) {
            if (ValidationRoutine()) {
              e.IsInputKey = true;  //If Validated, signals KeyDown to examine this key
            } //Side effect - This event is called twice when IsInputKey is set to true
          }          
        }
    
        private void comboBox1_KeyDown(object sender, KeyEventArgs e) {
          if (e.KeyData == Keys.Tab) {
              e.SuppressKeyPress = true; //Stops further processing of the TAB key
              btnEdit.Enabled = true;
              btnEdit.Focus();
          }
        }
    

    一旦您使用除None 以外的任何设置打开AutoCompleteModeKeyDown 事件就不会再为Tab 触发,密钥会被静默吃掉。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-22
      • 2021-05-21
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      相关资源
      最近更新 更多