About the First DataGridViewColumn Visible unexpected problem(关于第一列DataGridViewColumn意外可见的问题)
问题产生时的场景:
1. 一个Windows Form项目
2. Form1, 一个TabControl拥有两个TabPage被放到Form1上
3. 在tabPage1上放置dataGridView1和2个按钮button1、button2,在tabPage2上放置dataGridView2
4. 在Form1的Load事件处理方法中创建2个DataTable,分别是dt1、dt2(每个表都有三列),并分别绑定到dataGridView1、dataGridView2上,并把dataGridView1、dataGridView2的第一列的Visible属性设置为false,来隐藏第一列。
5. button1的Click事件处理方法用来更改dataGridView1的数据源表dt1, button2的Click事件处理方法用来更改dataGridView2的数据源表dt2
[在实例中只是向各自的DataTable添加一行数据]
6. 编译并启动一个程序实例,tabPage1显示了dataGridView1和两个按钮,还未切换到tabPage2,所以tabPage2和它上面的dataGridView2都还没绘制在桌面上
7. 记住,不要切换至tabPage2,保持dataGridView2一直不可见
8. 点击button1修改dt1,dataGridView1一切正常,为你添加了一行新值,并且事先隐藏掉的第一列也没有跳出来吓唬人,呵呵
9. 注意啦,现在点击button2修改dt2,即对一直还不可见的dataGridView2的数据源表进行操作,然后切换到tabPage2来显示dataGridView2,意外发生了,他就发生在你的眼前,第一列-那个事先在Form1 Load事件中已经隐藏掉的第一列竟然跳出来了,它竟然Visible了
老天可见,我在我的步骤中没有让你设置dataGridView2的第一列的Visible属性为true值啊!!!
问题分析:
当DataGridView控件的数据源进行操作的时候,CurrencyManager,这个Binding对象的管理者会检查它当前所在的位置。
在DataGridView中,它是怎么来确认自己的位置的呢,用reflector+Visual Studio分析+跟踪.Net源码,找到了它的确认过程:
先找出列的索引(其实问题就在这里,它以后的步骤就不分析了,对这个问题现在看来没有多大关系,所以我们只看这一段)
它会先确认CurrentCell,因为DataGridView不可见,所以没有CurrentCell,此时你也无法设置这个属性,这样的话,返回值就是一个初始的无效行列索引定位的cell,(-1,-1)。
当其判断返回值为-1时,他就会试图去直接取第一列的索引来代替无效的CurrentCell返回值,再试图获取第一列索引的时候,它会怀疑既然没有CurrentCell,那么是否意味着当前的DataGridView的Handle还未创建出来,因为dataGridView2还不可见呢,这个Handle当然还未创建出来了。
没办法,第一条路修改CurrentCell肯定走不通了,那是硬性规定现在是,想办法对这个IsHandleCreated属性做点手脚吧。
我也不大清楚为什么,反正在读取了一个控件的Handle属性之后,IsHandleCreated属性就变成true了,我对Windows的句柄、实例、窗体的绘制之间的关系不是很清楚,反正路是打通了,以后再慢慢学清楚这个Handle的创建吧。
再确认了当前的DataGridView的Handle已经创建了之后,它便会正确的去处可见列集合中的第一列索引了。
如果这个时候检测的Handle还未创建,那么它将直接返回-1,告诉剩下的程序这里连第一列都没有还搞个屁啊(其实是它只确定控件的Handle没有创建,剩下的工作还没做就返回了)。然后后面的程序便会试探的获取所有列中的第一列,包括隐藏中的列,然后将得到的第一列的Visible属性设置没true值(注意啦,原来是它,是源码把咋们的Visible属性设置为true了,让第一列蹦出来吓唬人),然后再继续做余下的工作。
解决方案:
好了,导致此非期望的现象的原因,大体分析出来了,解决方案也跟着出来了:
即在你对不可见的DataGridView数据源进行更改的时候,随便读一下它的Handle属性(DataGridView.Handle),使其IsHandleCreated属性早点为true,就一切OK了。
http://social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/75686026-be92-443f-a7f6-73cf26cdc37c
这个就是问题的来源,也是我写这边分析文字的初衷,花了我好长时间才追到代码出问题的大体位置,从接到帖子到跟踪代码,猜测+分析,到写完那个回复,足足花了我三个来小时的时间,蛋疼的问题啊!
看到之前还以为又是一个没有解决方案的bug,不过这个我感觉还真算一个小bug吧,最起码我感觉他的这个处理逻辑,在这方面做得不够强壮吧,我也是站着说话不腰疼,也不知道人家真要修这个bug会花多少资源,呵呵,YY一下。。。