C# WinForms组合框SelectedIndexChanged在键入几个字符并后跟Alt+;向下
简言之 在组合框中键入字符时,按Alt+Down,然后按Enter或Tab,即使SelectedIndex值发生更改,SelectedIndexChanged事件也不会触发!为什么活动没有启动 更新 如果键入字符,按Alt+Down,然后键入Esc,则会发生相同的错误。您可能希望Esc取消更改。但是,SelectedIndex确实会更改,并且SelectedIndexChanged事件不会触发 如果只需键入Alt+Down,使用箭头键浏览到某个条目,然后键入Esc,会发生什么情况?是否应将所选索引设置回其原始值C# WinForms组合框SelectedIndexChanged在键入几个字符并后跟Alt+;向下,c#,winforms,events,combobox,C#,Winforms,Events,Combobox,简言之 在组合框中键入字符时,按Alt+Down,然后按Enter或Tab,即使SelectedIndex值发生更改,SelectedIndexChanged事件也不会触发!为什么活动没有启动 更新 如果键入字符,按Alt+Down,然后键入Esc,则会发生相同的错误。您可能希望Esc取消更改。但是,SelectedIndex确实会更改,并且SelectedIndexChanged事件不会触发 如果只需键入Alt+Down,使用箭头键浏览到某个条目,然后键入Esc,会发生什么情况?是否应将所选索
不要太短 我有一个WinForm应用程序,上面有一个组合框。组合框的SelectedIndexChanged事件连接到一个事件处理程序,该事件处理程序在Label控件中显示SelectedItem。ComboBox的Items集合有三个值:“一”、“二”和“三”
- 当我用鼠标选择一个项目时,事件触发
- 当我滚动鼠标时,事件触发
- 当我使用Alt+Down展开组合框并使用Up和Down遍历项目时,会触发事件
- 但是。。。当我键入值的第一个字符,然后按Alt+Down,然后按Enter或Tab时,该值会被选中并显示在组合框中,但不会触发事件
One
,事件也不会触发,但在这种情况下,单击按钮会显示SelectedIndex确实没有更改。所以在这种情况下,这种行为是正常的
要复制,请创建一个表单并添加一个组合框、一个标签和一个按钮。将以下代码放入Form1.cs中:
using System;
using System.Windows.Forms;
namespace ComboBoxSelectedIndexChanged
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
comboBox1.Items.AddRange(new object[] {
"One",
"Two",
"Three"
});
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
label1.Text = "Selected index: " + comboBox1.SelectedIndex;
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Selected item: " + comboBox1.SelectedItem +
"\nSelected index: " + comboBox1.SelectedIndex);
}
}
}
此处适当的下拉属性值为DropDownList。它没有这个问题
对于下拉样式设置为DropDown的特定问题,很难找到解决方法。它允许用户输入任意文本,即使与其中一个下拉项完全匹配,也不会更改SelectedIndex。您必须实现验证事件并自己寻找匹配项。DropDownClosed事件适合您的特定场景。但实际上,如果你想要完美的匹配,一定要使用DropDownList。为了找到一个明确的答案,我尝试了几次谷歌搜索,但之前没有找到。刚才我发现一个线程实际上引用了一篇关于这个问题的Microsoft知识库文章。文章描述了这个问题 知识库文章建议您创建自己的组合框并重写ProcessDialogKey方法
using System.Windows.Forms;
public class MyComboBox : ComboBox
{
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Tab)
this.DroppedDown = false;
return base.ProcessDialogKey(keyData);
}
}
我试过了,但不幸的是,它似乎没有任何效果。这有点奇怪。我希望知识库文章中描述的解决方法是准确的
不过,我找到了另一种解决方法,那就是使用DropDownClosed事件代替
private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
label1.Text = "DroDownClosed Selected index: " + comboBox1.SelectedIndex;
}
这似乎确实有效,但只有在使用DropDownStyle.DropDown时才有效。将DropDownStyle设置为DropDownList时,键入字符不会触发DropDownClosed(因为在这种情况下没有实际的下拉)。仅当您实际打开下拉列表并选择一个值时,才会触发DropDownClosed事件
因此,这两种选择都不是一个好答案
更新
我甚至尝试在MyComboBox中重写属性SelectedIndex,让它调用SelectedIndexChanged(EventArgs.Empty)。在键入一个字符并按下Alt+Down键后,setter将被执行,但它正在将值设置为-1,而它已经设置为-1。按Tab键后,setter不会再次执行,尽管SelectedIndex值确实会发生变化。看起来ComboBox绕过设置直接更改SelectedIndex的支持字段。我相信在真正的组合框中也可能发生类似的情况。如果我错了,请纠正我。这是我用过的代码
comboBox1.Items.AddRange(new object[] {
"One",
"Two",
"Three"
});
comboBox1.SelectedIndexChanged+=(sa,ea)=>
{
label1.Text = "Selected index: " + comboBox1.SelectedIndex;
};
comboBox1.TextChanged+= (sa, ea) =>
{
comboBox1.SelectedIndex = comboBox1.FindStringExact(comboBox1.Text);
//OR
//comboBox1.SelectedIndex = comboBox1.Items.IndexOf(comboBox1.Text);
comboBox1.SelectionStart = comboBox1.Text.Length;
};
我在DropDownList样式的组合框上遇到了ESC问题。为了满足您的需求,我稍微修改了适合我的内容:
public class MyComboBox : System.Windows.Forms.ComboBox
{
private bool _sendSic;
protected override void OnPreviewKeyDown(System.Windows.Forms.PreviewKeyDownEventArgs e)
{
base.OnPreviewKeyDown(e);
if (DroppedDown)
{
switch(e.KeyCode)
{
case System.Windows.Forms.Keys.Escape:
_sendSic = true;
break;
case System.Windows.Forms.Keys.Tab:
case System.Windows.Forms.Keys.Enter:
if(DropDownStyle == System.Windows.Forms.ComboBoxStyle.DropDown)
_sendSic = true;
break;
}
}
}
protected override void OnDropDownClosed(System.EventArgs e)
{
base.OnDropDownClosed(e);
if(_sendSic)
{
_sendSic = false;
OnSelectedIndexChanged(System.EventArgs.Empty);
}
}
}
这样做的目的是在下拉菜单打开时听到输入的击键。如果是ESC、TAB或ENTER键用于下拉列表
-样式组合框或ESC键用于下拉列表
-样式组合框,则关闭下拉列表时会触发SelectedIndexChanged
-事件。我从未使用过
ComboBoxStyle.Simple
,也不知道它是如何工作的,但就我所知,它从来没有显示过下拉列表,因此即使对于那种样式,这也应该是安全的
如果您不想从
ComboBox
派生来构建自己的控件,也可以通过订阅表单上的ComboBox的PreviewKeyDown
和DropDownClosed
事件,将类似的逻辑应用于该ComboBox
public class EditableComboBox : ComboBox
{
protected int backupIndex;
protected string backupText;
protected override void OnDropDown(EventArgs e)
{
backupIndex = this.SelectedIndex;
if (backupIndex == -1) backupText = this.Text;
else backupText = null;
base.OnDropDown(e);
}
protected override void OnSelectionChangeCommitted(EventArgs e)
{
backupIndex = -2;
base.OnSelectionChangeCommitted(e);
}
protected override void OnSelectionIndexChanged(EventArgs e)
{
backupIndex = -2;
base.OnSelectionIndexChanged(e);
}
protected override void OnDropDownClosed(EventArgs e)
{
if (backupIndex > -2 && this.SelectedIndex != backupIndex)
{
if (backupIndex > -1)
{
this.SelectedIndex = backupIndex;
}
else
{
string oldText = backupText;
this.SelectedIndex = -1;
this.Text = oldText;
this.SelectAll();
}
}
base.OnDropDownClosed(e);
}
}
我发现了同样的问题,所以我处理了TextChanged事件。根据MSDN页面-SelectedIndexChanged事件将在SelectedIndex属性的值更改时触发。@adatapost:我在这里描述事情的方式(键入第一个字符,然后Alt+Down),然后单击按钮)表明SelectedIndex确实更改。我的情况不是用户在完整条目中键入,只需输入第一个字符,然后按Alt+Down键。正如我的按钮所显示的,这样它确实改变了SelectedIndex。这正是让我吃惊的地方。SelectedIndex确实会更改,但事件不会触发。是的,很遗憾,不是吗?我的观点是,除非将下拉样式设置为DropDownList,否则永远不能依赖SelectedIndex。你试过了吗?是的,我试过了。但通过使用下拉式,它不再是一个真正的组合框。