日期:2014-05-17  浏览次数:21550 次

C#:ComboBox中TextChanged事件不被触发的探究

ComboBox的TextChanged事件是应用很广的一个事件。该事件会在ComboBox的编辑框内文字发生改变的时候触发。

但是有一次在项目里,当我选择了ComboBox的下拉项的时候,它神奇的没有被触发。


重现的方式也很简单。先新建一个类,写一个这样的控件。


 using System;
 using System.Collections.Generic;
 using System.Text;
 using System.Windows.Forms;
 using System.Data;
 
 namespace WindowsFormsApplication1
 {
     public class TestComboBox : Control
     {
         public event EventHandler _TextChanged;
 
         public TestComboBox()
         {
             //创建一个comboBox
             ComboBox m_combo = new ComboBox();
             m_combo.Size = new System.Drawing.Size(100, 20);
             m_combo.Location = new System.Drawing.Point(0, 0);
             m_combo.Name = "comboBox1";
             m_combo.TabIndex = 0;
 
             //构造用于绑定到comboBox的DataSource
             DataTable table = new DataTable();
             table.Columns.Add("code");
             table.Columns.Add("name");
 
             table.Rows.Add("1", "AA");
             table.Rows.Add("2", "BB");
 
             //设定绑定方式
             m_combo.DataSource = table;
             m_combo.DisplayMember = "name";
             m_combo.ValueMember = "code";
 
             //注册TextChanged事件
             m_combo.TextChanged += new EventHandler(m_combo_TextChanged);
 
             this.Controls.Add(m_combo);
         }
 
         private void m_combo_TextChanged(object sender, EventArgs e)
         {
             if (_TextChanged != null)
             {
                 _TextChanged(sender, e);
             }
         }
     }
 }


编译之后,把这个控件拖到窗体上,然后注册_TextChanged事件。

运行之后,会发现无论在ComboBox的下拉项里选择什么,只要焦点没有离开该控件,_TextChanged事件就一直不会有任何反应。

而标准的ComboBox在同样的情况下,只要选择下拉项里一个不同的项,TextChanged事件就立刻会被触发。

这个一个现象让我感到很困惑。


调查来调查去,发现有一个属性很关键。

 m_combo.FormattingEnabled = true;

将这句代码加入到上面那个类的构造函数中之后,事件就可以正常触发了。

这个FormattingEnabled属性到底是何方神圣?

查阅MSDN的资料,只是说明,该控件的DisplayMember是否使用自定义的Format字符串。

感觉这个属性不应该要影响这么基本的一个事件才对。


但是有一个很诡异的事情是。

当我们从工具栏拖一个标准的comboBox到画面上之后。你会发现FormattingEnabled属性立刻被改写成了True。

而且还是以粗体显示,代表FormattingEnabled的默认值并不是True。

在FormattingEnabled属性上点击右键,将其重置回默认值就可以看到,FormattingEnabled的默认值是False。


而通常情况下我们用代码手写控件,动态创建ComboBox的时候,并没有意识到这个属性必须设置成True,所以少写了这个代码。

从而TextChanged事件不会触发。


于是去查看了一下ComboBox的源码,发现有这么一段代码:

case NativeMethods.CBN_CLOSEUP:
  
                     OnDropDownClosed(EventArgs.Empty); 
                     if (FormattingEnabled && Text != currentText && dropDown) {
                         OnTextChanged(EventArgs.Empty); 
                     }
                     dropDown = false;
                     break;

从这段代码来看,表达的意思是,在DropDown关闭之后,也就是你选择了一个项之后。

首先执行OnDropDownClosed函数

而OnTextChanged函数的执行则要看3个条件是否都为True。其中一项就包括了FormattingEnabled这个属性。

所以这个属性若没设置成True,通过选择下拉项来改变ComboBox内的文字,是不会触发TextChanged事件的。


在这里我不禁感到奇怪,既然FormattingEnabled属性关系到TextChanged这么基础的一个事件,为何默认值是False而不是True?

真是令人费解。


转载请注明出处。