我們今天將要講到DataGridView之行的展開與收縮,包括功能是如何實現的,感興趣的小伙伴們可以參考一下
很多數據都有父節點與子節點,我們希望單擊父節點的時候可以展開父節點下的子節點數據。
比如一個醫院科室表,有父科室與子科室,點擊父科室后,在父科室下面可以展現該科室下的所有子科室。
我們來說一下在DataGridView中如何實現這個功能。
首先,創建示例數據:
示例數據SQL
- create table Department
- (
- ID int identity(1,1) not null,
- DName varchar(20) null,
- DparentId int null,
- Dtelphone varchar(20) null,
- Dhospital varchar(50) null
- )
- insert into Department values('門診外室',1,'1111','XXX醫院')
- insert into Department values('門診內科',1,'2222','XXX醫院')
- insert into Department values('門診手術',1,'3333','XXX醫院')
- insert into Department values('門診兒科',1,'4444','XXX醫院')
- insert into Department values('神經內室',2,'5555','XXX醫院')
- insert into Department values('神經外科',2,'6666','XXX醫院')
- insert into Department values('住院手術',2,'7777','XXX醫院')
- insert into Department values('住院康復',2,'8888','XXX醫院')
其實思路很簡單,就是在展開父節點的時候,在父節點下插入新的DataGridViewRow;收縮父節點的時候,在父節點下刪除該子節點的DataGridViewRow。
為了簡便,代碼中的數據讀取我都直接硬編碼了。
加載父節點數據,除了數據庫中的列外我還新加了兩列:IsEx與EX。
- private void DataGridBing(DataTable table)
- {
- if (table.Rows.Count > 0)
- {
- for (int i = 0; i < table.Rows.Count; i++)
- {
- int k = this.dataGridView1.Rows.Add();
- DataGridViewRow row = this.dataGridView1.Rows[k];
- row.Cells["ID"].Value = table.Rows[i]["ID"];
- row.Cells["DName"].Value = table.Rows[i]["DName"];
- row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
- row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
- //用于顯示該行是否已經展開
- row.Cells["IsEx"].Value = "false";
- //用于顯示展開或收縮符號,為了簡單我就直接用字符串了,其實用圖片比較美觀
- row.Cells["EX"].Value = "+";
- }
- }
- }
下面就是Cell的單擊事件了,分別在事件中寫展開的插入與收縮的刪除.
插入子節點:
- string isEx=this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value.ToString();
- if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx=="false")
- {
- string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
- DataTable table = GetDataTable("select * from Department where DparentId="+id);
- if (table.Rows.Count > 0)
- {
- //插入行
- this.dataGridView1.Rows.Insert(e.RowIndex+1, table.Rows.Count);
- for (int i = 0; i < table.Rows.Count; i++)
- {
- DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex + i+1];
- row.DefaultCellStyle.BackColor = Color.CadetBlue;
- row.Cells["ID"].Value = table.Rows[i]["ID"];
- row.Cells["DName"].Value = table.Rows[i]["DName"];
- row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
- row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
- }
- }
- //將IsEx設置為true,標明該節點已經展開
- this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "true";
- this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "-";
刪除子節點:
- if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx == "true")
- {
- string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
- DataTable table = GetDataTable("select * from Department where DparentId=" + id);
- if (table.Rows.Count > 0)
- {
- //利用Remove
- for (int i = 0; i < table.Rows.Count; i++)
- {
- foreach (DataGridViewRow row in this.dataGridView1.Rows)
- {
- if (row.Cells["ID"].Value.Equals(table.Rows[i]["ID"]))
- {
- this.dataGridView1.Rows.Remove(row);
- }
- }
- }
- }
- ////將IsEx設置為false,標明該節點已經收縮
- this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "false";
- this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "+";
- }
這里面通過比較ID來唯一確定一行,循環比較多,因為子節點是緊接著父節點的,我們可以確定子節點所在的行數,所以用RemoveAt()方法更好。
- //利用RemoveAt
- for (int i = table.Rows.Count; i > 0; i--)
- {
- //刪除行
- this.dataGridView1.Rows.RemoveAt(i + e.RowIndex);
- }
上面的做法是通過不斷的插入與刪除來實現,但這樣與數據庫的交互變得很頻繁。更好的做法應該是插入一次,然后通過隱藏或顯示行來實現我們的效果。
為此,我們還要在grid中新增兩個列:
IsInsert:用來判斷該行是否已經有插入子節點數據
RowCount:用來保存該行下插入的子節點數量。
在方法DataGridBing中,綁定數據時,應該再加一列:
- //是否插入
- row.Cells["IsInsert"].Value = "false";
而在增加節點的時候,我們要多做一個判斷,如果IsInsert為false就插入數據,如果為true就顯示數據
展開行
- if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx=="false")
- {
- if (this.dataGridView1.Rows[e.RowIndex].Cells["IsInsert"].Value.ToString() == "false")
- {
- string id = this.dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString();
- DataTable table = GetDataTable("select * from Department where DparentId=" + id);
- if (table.Rows.Count > 0)
- {
- //插入行
- this.dataGridView1.Rows.Insert(e.RowIndex + 1, table.Rows.Count);
- for (int i = 0; i < table.Rows.Count; i++)
- {
- DataGridViewRow row = this.dataGridView1.Rows[e.RowIndex + i + 1];
- row.DefaultCellStyle.BackColor = Color.CadetBlue;
- row.Cells["ID"].Value = table.Rows[i]["ID"];
- row.Cells["DName"].Value = table.Rows[i]["DName"];
- row.Cells["Daddress"].Value = table.Rows[i]["Daddress"];
- row.Cells["Dtelphone"].Value = table.Rows[i]["Dtelphone"];
- }
- this.dataGridView1.Rows[e.RowIndex].Cells["IsInsert"].Value = "true";
- this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value = table.Rows.Count;
- }
- }
- else
- {
- //顯示數據
- int RowCount = Convert.ToInt32(this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value);
- for (int i = 1; i <= RowCount; i++)
- {
- this.dataGridView1.Rows[e.RowIndex + i].Visible = true;
- }
- }
- //將IsEx設置為true,標明該節點已經展開
- this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "true";
- this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "-";
- }
收縮的時候,我們直接隱藏行就可以了.
收縮行
- if (this.dataGridView1.Columns[e.ColumnIndex].Name == "EX" && isEx == "true")
- {
- int RowCount = Convert.ToInt32(this.dataGridView1.Rows[e.RowIndex].Cells["RowCount"].Value);
- for (int i = 1; i <= RowCount; i++)
- {
- //隱藏行
- this.dataGridView1.Rows[e.RowIndex + i].Visible = false;
- }
- ////將IsEx設置為false,標明該節點已經收縮
- this.dataGridView1.Rows[e.RowIndex].Cells["IsEx"].Value = "false";
- this.dataGridView1.Rows[e.RowIndex].Cells["EX"].Value = "+";
- }
大家知道DataGridView是如何實現展開收縮的吧,希望大家不僅知道是如何實現的還要動手實驗一番,才不枉小編辛苦整理此文章哦
新聞熱點
疑難解答
圖片精選