GridViewCheckBoxColumn以CheckBox的形式顯示、編輯bool值,實現行選中效果。 如果需要在表頭添加全選框,可以將EnableHeaderCheckBox設置為true: ```C# private void AddCheckColumn() { checkColumn = ...
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_csharp\RadForm1.cs:line 82
根據異常調用堆棧,發現是在Telerik內部報錯,直接反編譯調試下,在GridCheckBoxHeaderCellElement.UpdateCheckboxReadOnly()處設置斷點,看看為什麼導致空指針。查看this無法計算表達式,可以編輯下方法,加幾個判斷:
可以看到,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);
}
}
轉載請註明出處,歡迎交流。