EnableHeaderCheckBox导致空指针

  • EnableHeaderCheckBox导致空指针已关闭评论
  • 156 次浏览
  • A+
所属分类:.NET技术
摘要

GridViewCheckBoxColumn以CheckBox的形式显示、编辑bool值,实现行选中效果。如果需要在表头添加全选框,可以将EnableHeaderCheckBox设置为true:

GridViewCheckBoxColumn以CheckBox的形式显示、编辑bool值,实现行选中效果。

如果需要在表头添加全选框,可以将EnableHeaderCheckBox设置为true:

private void AddCheckColumn() {     checkColumn = new GridViewCheckBoxColumn();     checkColumn.Name = "Select";     checkColumn.HeaderText = "All";     checkColumn.EnableHeaderCheckBox = true;     this.radGridView1.Columns.Insert(0, checkColumn);     this.radGridView1.HeaderCellToggleStateChanged += RadGridView1_HeaderCellToggleStateChanged; }  private void RadGridView1_HeaderCellToggleStateChanged(object sender, GridViewHeaderCellEventArgs e) {     MessageBox.Show($"状态:{e.State}"); } 

通过监听RadGridView的HeaderCellToggleStateChanged事件监听表头的全选框状态。除了切换表头的全选框状态时会触发该事件,切换列的CheckBox时如果同时切换了表头的全选框状态,也会触发该事件。

问题:

使用过程中,发现GridView隐藏再显示会报空指针异常。

分析

报错发生在GridView设置只读属性的位置,异常调用堆栈如下:

at Telerik.WinControls.UI.GridCheckBoxHeaderCellElement.UpdateCheckboxReadOnly() at Telerik.WinControls.UI.GridCheckBoxHeaderCellElement.MasterTemplate_PropertyChanged(Object sender, PropertyChangedEventArgs e) at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e) at Telerik.WinControls.UI.GridViewTemplate.OnNotifyPropertyChanged(PropertyChangedEventArgs e) at Telerik.WinControls.UI.MasterGridViewTemplate.OnNotifyPropertyChanged(PropertyChangedEventArgs e) at Telerik.WinControls.UI.GridViewTemplate.SetProperty[T](String propertyName, T& propertyField, T value) at Telerik.WinControls.UI.MasterGridViewTemplate.set_GridReadOnly(Boolean value) at Telerik.WinControls.UI.RadGridView.set_ReadOnly(Boolean value) at CheckBoxInHeader_csharp.RadForm1.<AddButton>b__8_2(Object o, EventArgs e) in CheckBoxInHeader_csharpRadForm1.cs:line 82 

根据异常调用堆栈,发现是在Telerik内部报错,直接反编译调试下,在GridCheckBoxHeaderCellElement.UpdateCheckboxReadOnly()处设置断点,看看为什么导致空指针。查看this无法计算表达式,可以编辑下方法,加几个判断:

EnableHeaderCheckBox导致空指针

可以看到,this.ColumnInfo为空。继续调试,发现EnableHeaderCheckBox设置为true的列如果被隐藏,当设置GridView的Readonly属性的时候就会触发该异常,这是UI框架的BUG。

解决

可以自己实现GridCheckBoxHeaderCellElement,不用官方的,参考文档,这比较麻烦。简单处理,加个try-catch捕获下吧。以下是测试代码,先点击测试1,再点击测试2就会触发该异常。

public partial class RadForm1 : RadForm {     private bool flag1 = false;     private bool flag2 = false;     private GridViewCheckBoxColumn checkColumn;      public RadForm1()     {         InitializeComponent();         AddCheckColumn();         AddButton();          this.radGridView1.RowCount = 10;         this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;         this.radGridView1.MasterTemplate.AllowAddNewRow = false;     }      private void AddCheckColumn()     {         checkColumn = new GridViewCheckBoxColumn();         checkColumn.Name = "Select";         checkColumn.HeaderText = "All";         checkColumn.EnableHeaderCheckBox = true;         this.radGridView1.Columns.Insert(0, checkColumn);         this.radGridView1.HeaderCellToggleStateChanged += RadGridView1_HeaderCellToggleStateChanged;          this.radGridView1.Columns.Add(new GridViewTextBoxColumn("A"));         this.radGridView1.Columns.Add(new GridViewTextBoxColumn("B"));     }      private void RadGridView1_HeaderCellToggleStateChanged(object sender, GridViewHeaderCellEventArgs e)     {         MessageBox.Show($"状态:{e.State}");     }      private void AddButton()     {         Button btn1 = new Button();         btn1.Text = "测试1";         btn1.Click += (o, e) =>         {             checkColumn.IsVisible = flag1;             flag1 = !flag1;         };         btn1.Location = new Point(5, 5);         this.Controls.Add(btn1);          Button btn2 = new Button();         btn2.Text = "测试2";         btn2.Click += (o, e) =>         {             if (flag2)                 radGridView1.Hide();             else             {                 radGridView1.Show();                 try                 {                     radGridView1.ReadOnly = flag2;                 }                 catch { }             }             flag2 = !flag2;         };         btn2.Location = new Point(120, 5);         this.Controls.Add(btn2);     } }