您现在的位置: 365建站网 > 365学习 > C#/vb.net-中SelectedIndexChanged事件, SelectedValueChanged事件和SelectionChangeCommitted事件的区别和用法

C#/vb.net-中SelectedIndexChanged事件, SelectedValueChanged事件和SelectionChangeCommitted事件的区别和用法

文章来源:365jz.com     点击数:295    更新时间:2018-01-05 16:48   参与评论

SelectedIndexChanged事件


索引改变时即触发吗,可以通过编程触发

SelectedValueChanged事件


值改变时触发,可以通过编程触发

SelectionChangeCommitted事件


在设定datasource和displaymember和valuemember时,以及手动改变combobox索引和值时都不触发该事件, 只是在界面选择combobox不同值时触发,即只有通过界面点击修改combobox的值才会触发此事件

区别


1、SelectedIndexChanged和SelectedValueChanged可以通过编程的方式更改属性而触发事件,但SelectionChangeCommitted事件必须由用户操作选定选项才能触发。

2、在初始化时(设置源)SelectedIndexChanged和SelectedValueChanged都会被调用,而SelectionChangeCommitted没有这个问题。

不同的代码顺序触发的先后顺序和次数


关于在编程时通过设置DataSource, DisplayMember, ValueMember不同顺序均可触发SelectedIndexChanged事件和SelectedValueChanged事件的次数,但是不会触发SelectionChangeCommitted

顺序一


this.comboBox1.DisplayMember = "userName";  (不触发)

this.comboBox1.ValueMember = "userAge";    (只触发SelectedValueChanged)

this.comboBox1.DataSource = dt; (都触发)

SelectedValueChanged触发两次(总是先触发)SelectedIndexChanged,触发一次 (设置DisplayMember属性时不触发两种事件)

顺序二


this.comboBox1.ValueMember = "userAge"; (只触发SelectedValueChanged)

this.comboBox1.DisplayMember = "userName";(不触发)

this.comboBox1.DataSource = dt; (两者都触发)

同上,SelectedValueChanged触发两次(总是先触发)SelectedIndexChanged,触发一次 (设置DisplayMember属性时不触发两种事件)

顺序三


this.comboBox1.DataSource = dt; (都触发)

this.comboBox1.DisplayMember = "userName";(都触发)

this.comboBox1.ValueMember = "userAge";(只触发SelectedValueChanged事件)

SelectedValueChanged触发三次(总是先触发)SelectedIndexChanged,触发两次 (设置DisplayMember属性时不触发两种事件)

顺序四:


this.comboBox1.DataSource = dt; (都触发)

this.comboBox1.ValueMember = "userAge";(都触发) 其中SelectedValueChanged触发两次

this.comboBox1.DisplayMember = "userName";(都触发)

SelectedValueChanged触发四次(总是先触发)SelectedIndexChanged,触发三次 (设置DisplayMember属性时不触发两种事件)

分析


说明:当设置了DataSource 属性后,SelectedValue 属性值会默认为第一行(所以会触发SelectedIndexChanged事件和SelectedValueChanged事件),因此,如果不希望ComboBox自动选择第一行,还需在设置完DataSource 后自行将SelectedValue 设为“”。

ComboBox最经常使用的事件就是SelectedIndexChanged。但在将ComboBox绑定到某个数据源的过程中,会触发SelectedIndexChanged
事件,而这个时候用户并没有选择内容,其SelectedValue也不是对应字段的值。那么时写在SelectedIndexChanged中的处理代码就会因为SelectedValue的内容不正确引发异常。
一般网上找到的方法是添加一个标记位,在绑定前设置为false,绑定完成后设置回true。

void BindComboBox()
{
    flag=false;
    ComboxBox1.ValueMember="ValueColumn";
    ComboxBox1.DisplayMember="DisplayColumn";
    ComboxBox1.DataSource=DataTable1;
    flag=true;
}

private void ComboxBox1_SelectedIndexChanged(object sender, EventArgs e)
{
     if(flag)
     {
          //Do something
      }  
}

另外还有一种办法,就是在绑定前,将SelectedIndexChanged的委托去掉,等绑定完成后,再添加事件委托。

void BindComboBox()
{          //去除委托
            ComboBox1.SelectedIndexChanged -= new EventHandler(ComboBox1_SelectedIndexChanged);          
            ComboBox1.DataSource = null;
            ComboBox1.ValueMember = "ValueColumn";         
            ComboBox1.DataSource = DataTable1;
            //添加委托
            ComboBox1.SelectedIndexChanged += new EventHandler(ComboBox1_SelectedIndexChanged);
            ComboBox1.DisplayMember = "DisplayColumn";
}
两种方法都可以,但是之间的优劣暂时没去比较。感觉好像处理一下委托会好点。因为这种办法真的减少了事件的激发次数。
不知道还有没有其他解决方案呢?
另,贴上一段完整的代码例子。这个例子是访问SQLServer数据库的AdventureWorks,通过ProductCategory和ProductSubCategory两级目录分类去查看Product表的内容。分别使用两个ComboBox和DataGridView完成数据绑定。效果就是选择之后会联动改变相关内容。
public partial class frmProduct : Form
    {
DataSet DS = new DataSet();
        String ConnectionString = "integrated security=true; database=AdventureWorks;  server=localhost; ";
        public frmProduct()
        {
            InitializeComponent();
        }
      
        private void frmProduct_Load(object sender, EventArgs e)
        {
            SqlDataAdapter da = new SqlDataAdapter("select ProductCategoryID,[Name] from Production.ProductCategory", ConnectionString)
;
            cbbCategories.SelectedIndexChanged -= new EventHandler(cbbCategories_SelectedIndexChanged);
            da.Fill(DS, "ProductCategory");
            cbbCategories.DataSource = null;
            cbbCategories.ValueMember = "ProductCategoryID";         
            cbbCategories.DataSource = DS.Tables["ProductCategory"];
            cbbCategories.SelectedIndexChanged += new EventHandler(cbbCategories_SelectedIndexChanged);
            cbbCategories.DisplayMember = "Name";//这句放在事件委托之后才会有联动效果,下同
        }

        private void cbbCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            SqlDataAdapter da = new SqlDataAdapter("select ProductSubCategoryID,[Name] from Production.ProductSubCategory where  ProductCategoryID=" + cbbCategories.SelectedValue.ToString(), ConnectionString)
;
            if (DS.Tables["ProductSubCategory"] != null)
            {
                DS.Tables["ProductSubCategory"].Clear();
            }
            da.Fill(DS, "ProductSubCategory");
            cbbSubCategories.SelectedIndexChanged -= new EventHandler(cbbSubCategories_SelectedIndexChanged);
            cbbSubCategories.DataSource = null;          
            cbbSubCategories.ValueMember = "ProductSubCategoryID";
            cbbSubCategories.DataSource = DS.Tables["ProductSubCategory"];
            cbbSubCategories.SelectedIndexChanged += new EventHandler(cbbSubCategories_SelectedIndexChanged);
            cbbSubCategories.DisplayMember = "Name";
        }      

        private void cbbSubCategories_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbbSubCategories.SelectedIndex == -1)
                return;
            SqlDataAdapter da=new SqlDataAdapter("select * from Production.Product where  ProductSubCategoryID=" + cbbSubCategories.SelectedValue.ToString(), ConnectionString);
            dgvProduct.DataSource = null;
            if (DS.Tables["Product"] != null)
                DS.Tables["Product"].Clear();
            da.Fill(DS, "Product");
            dgvProduct.DataSource = DS.Tables["Product"];
        }
    }

如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛


发表评论 (295人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
用户名: 验证码: 点击我更换图片
最新评论
------分隔线----------------------------