C#中ComboBox的SelectedIndexChanged事件由于触发时间而引起的“未将对象引用到对象实例”错误解决

今天偶尔复习下WinForm开发,在用到ComboBox下拉框的时候,想用SelectedIndexChanged事件根据选中内容动态展示不同的数据,需求很简单,但是竟然出错了,后来发现其实就是SelectedIndexChanged事件执行时间问题导致的,那如何解决呢,请看下面的分析。

一、DataBind()方法就是给下拉框绑定的方法(这里为了让下拉框默认不选中,设置了SelectedIndex = -1)这个位置就是出问题的地方

       //数据绑定
        private void DataBind()
        {
            //角色权限设置绑定下拉列表
            this.cboRoleList.DataSource = null;
            this.cboRoleList.DataSource = objAdminRole;
            this.cboRoleList.DisplayMember = "RoleName";
            this.cboRoleList.ValueMember = "RoleId";
            //去掉下拉列表的默认值
            this.cboRoleList.SelectedIndex = -1;
        }

二、这里触发了 SelectedIndexChanged事件,实现根据选中内容不同实现不同的切换(方法内部实现的啥可以不用关心)

       //下拉列表改变时触发的事件
        private void cboRoleList_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.tvRightList.Nodes.Clear();
            List<FirstMenu> GetAllFirstMenuRoleId = objRightManager.GetAllFirstMenu(((AdminRole)(this.cboRoleList.SelectedItem)).RoleId);
            for (int i = 0; i < GetAllFirstMenuRoleId.Count; i++)
            {
                TreeNode objNode = new TreeNode()
                {
                    Name = GetAllFirstMenuRoleId[i].FirstMenuId.ToString(),
                    Text=GetAllFirstMenuRoleId[i].DisplayName
                };
                List<SecondMenu> GetAllSecondMenuRoleId = objRightManager.GetAllSecondMenu(GetAllFirstMenuRoleId[i].FirstMenuId, ((AdminRole)(this.cboRoleList.SelectedItem)).RoleId);
                for (int j = 0; j < GetAllSecondMenuRoleId.Count; j++)
                {
                    objNode.Nodes.Add(new TreeNode() {
                        Name= GetAllSecondMenuRoleId[j].SecondMenuId.ToString(),
                        Text=GetAllSecondMenuRoleId[j].DisplayName,
                        ForeColor=Color.Blue
                    });
                    List<RightList> GetAllRightListRoleId = objRightManager.GetAllRightList(GetAllSecondMenuRoleId[j].SecondMenuId, ((AdminRole)(this.cboRoleList.SelectedItem)).RoleId);
                    for (int k = 0; k < GetAllRightListRoleId.Count; k++)
                    {
                        objNode.Nodes[j].Nodes.Add(new TreeNode() {
                            Name=GetAllRightListRoleId[k].RightId.ToString(),
                            Text=GetAllRightListRoleId[k].RightName,
                            ForeColor=Color.Red,
                            Tag=GetAllRightListRoleId[k].RightCode
                        });
                    }
                }

                this.tvRightList.Nodes.Add(objNode);
            }
            //将整个节点展开
            this.tvRightList.ExpandAll();
        }

 三、在这里定义了GetAllRoleRight()方法,这个方法本身在窗体初始化之后立即调用,方法内部是调用了上面的DataBind()方法。这时候就会出错,报的错误就是最常见的"未将对象引用到对象实例",

 //绑定当前系统全部角色
        public void GetAllRoleRight()
        {   
            //为角色集合添加数据库全部角色
            objAdminRole =objRightManager.GetAllRole();
            //数据绑定
            DataBind();           
        }

错误原因:

SelectedIndexChanged事件是在绑定的时候就会触发,意思就是在设置SelectedIndex = -1的时候事件就已经被触发了,并立即调用步骤二中的事件响应方法cboRoleList_SelectedIndexChanged,而这时候,该方法第二行:List<FirstMenu> GetAllFirstMenuRoleId = objRightManager.GetAllFirstMenu(((AdminRole)(this.cboRoleList.SelectedItem)).RoleId);还没有来得及获得任何数据,故此时,程序会立即报错:未将对象引用到对象的实例。好了原因分析清楚了,那就说一下解决办法。

解决办法:手动断开/连接事件响应方法

在调用  DataBind()方法(设置SelectedIndex = -1)之前,即调用cboRoleList_SelectedIndexChanged()事件响应方法之前,断开事件与事件响应方法的关联,之后在调用后,再将事件与事件响应方法进行关联就好了。将方法三代码加两句(如下)

 //绑定当前系统全部角色
        public void GetAllRoleRight()
        {
            //先将(下拉列表改变时触发的事件)事件解绑
            this.cboRoleList.SelectedIndexChanged -= new System.EventHandler(this.cboRoleList_SelectedIndexChanged);

            //为角色集合添加数据库全部角色
            objAdminRole =objRightManager.GetAllRole();
            //数据绑定
            DataBind();

            //再将(下拉列表改变时触发的事件)事件添加绑定
            this.cboRoleList.SelectedIndexChanged += new System.EventHandler(this.cboRoleList_SelectedIndexChanged);
        }

这样在调用  DataBind()方法(设置SelectedIndex = -1)(即调用cboRoleList_SelectedIndexChanged()事件响应方法)时候就不会触发SelectedIndexChanged事件。就不会报错了。

猜你喜欢

转载自blog.csdn.net/qq_42539194/article/details/106007099