![](/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.