![](/img/trans.png)
[英]Not firing the SelectedIndexChanged when using jquery combobox
[英]WinForms ComboBox SelectedIndexChanged not firing when typing few chars followed by Alt+Down
简而言之
当我在ComboBox中键入一个字符时,按Alt +向下键,然后按Enter键或Tab键,即使SelectedIndex值确实发生更改,也不会触发SelectedIndexChanged事件! 为什么事件没有发生?
更新如果键入字符,则按Alt +向下键,然后键入Esc,则会出现相同的错误。 您可能希望Esc取消更改。 但是,SelectedIndex 会更改,并且不会触发SelectedIndexChanged事件。
如果只键入Alt + Down,使用箭头键浏览条目, 然后键入Esc,会发生什么? 是否应将所选索引设置回其原始值?
不是那么短暂
我有一个带有ComboBox的WinForm应用程序。 ComboBox的SelectedIndexChanged事件连接到一个事件处理程序,该事件处理程序显示Label控件中的SelectedItem。 ComboBox的Items集合有三个值:“One”,“Two”和“Three”。
我还添加了一个显示SelectedIndex的按钮。 它显示SelectedIndex 已更改。 因此,即使SelectedIndex确实发生了变化,SelectedIndexChanged事件也不会触发!
如果我只输入一个有效值,如 One
则事件也不会触发,但在这种情况下单击按钮会显示SelectedIndex确实没有更改。 所以在这种情况下行为是正常的。
要重现,请创建一个表单并添加一个ComboBox,一个Label和一个Button。 将以下代码放在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);
}
}
}
我已经尝试了几次谷歌搜索,以便找到一个明确的答案,但之前没有找到。 刚才我找到了一个线程,实际上是指有关该问题的Microsoft知识库文章。 文章KB948869描述了该问题。
知识库文章建议创建自己的组合框并覆盖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,让它调用OnSelectedIndexChanged(EventArgs.Empty)
。 键入字符并按Alt + Down后,执行setter,但它将值设置为-1,它已经是。 按下Tab后,不会再次执行setter,尽管SelectedIndex值会以某种方式更改。 看起来ComboBox正在直接更改SelectedIndex的支持字段,绕过设置。 我相信这样的事情也可能发生在真正的ComboBox中。
这里适当的DropDown属性值是DropDownList。 它没有这个问题。
针对DropDown样式设置为DropDown的特定问题的解决方法非常困难。 它允许用户键入任意文本,甚至与其中一个下拉项完美匹配也不会更改SelectedIndex。 您必须实现Validating事件并自己查找匹配项。 DropDownClosed事件对您的特定场景有用。 但实际上,如果你想完美匹配,总是使用DropDownList。
我在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或输入一个DropDown
式的组合框或ESC的DropDownList
风格的组合框,一个SelectedIndexChanged
当下拉关闭-活动被触发。
我从来没有使用过ComboBoxStyle.Simple
,也不知道它是如何工作的,但是因为据我所知,它永远不会显示DropDown,即使对于那种风格也应该是安全的。
如果您不想从ComboBox
派生来构建自己的控件,您还可以通过订阅它的PreviewKeyDown
和DropDownClosed
事件将类似的逻辑应用于表单上的ComboBox。
如我错了请纠正我。 这是我用过的代码。
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;
};
我最终从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);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.