在c# winform下做過項目的朋友都知道,其中的datagridview控制項預設只支援datagridviewbuttoncolumn、datagridviewcheckboxcolumn、datagridviewcomboboxcolumn、datagridviewimagecolumn、datagridviewlinkcolumn和datagridviewtextboxcolumn六種列類型,如果你想要在datagridview的列中添加其它的子控制項,則需要自己實現datagridviewcolumn和datagridviewcell,這就意味著你需要從現有的列中繼承並改寫一些方法,如實現一個支援選項按鈕的列,或支援三種選擇狀態的多選按鈕的列。
{
function onclick()
{
get_larger(this)
}
}" src="resourse/images/resimages/article/5011/0.gif" alt="c# winform下datagridview單元按鈕列">
{
function onclick()
{
get_larger(this)
}
}" src="Resourse/Images/ResImages/Article/5011/1.gif" alt="c# winform下datagridview單元按鈕列">
上面兩個分別為radiobutton列和支援三種狀態的checkbox列在datagridview中的實現效果,我是在windows 2003中實現的,因此顯示的效果跟在xp和vista下有些區別,vista下checkbox的第三種狀態(不確定狀態)顯示出來的效果是一個實心的藍色方塊。
下面我看具體來看看如何?這兩種效果。
要實現自訂的datagridview列,你需要繼承並改寫兩個類,一個是基於datagridviewcolumn的,一個是基於datagridviewcell的,因為radionbutton和checkbox的實現原理類似,因此我們可以將這兩種列採用同一種方法實現。建立datagridviewdisablecheckboxcell和datagridviewdisablecheckboxcolumn兩個類,分別繼承自datagridviewcheckboxcell和datagridviewcheckboxcolumn。代碼如下:
public class datagridviewdisablecheckboxcell: datagridviewcheckboxcell
{
public bool enabled { get; set; }
// override the clone method so that the enabled property is copied.
public override object clone()
{
datagridviewdisablecheckboxcell cell = (datagridviewdisablecheckboxcell)base.clone();
cell.enabled = this.enabled;
return cell;
}
// by default, enable the checkbox cell.
public datagridviewdisablecheckboxcell()
{
this.enabled = true;
}
// three state checkbox column cell
protected override void paint(graphics graphics, rectangle clipbounds, rectangle cellbounds, int rowindex,
datagridviewelementstates elementstate, object value, object formattedvalue, string errortext,
datagridviewcellstyle cellstyle, datagridviewadvancedborderstyle advancedborderstyle, datagridviewpaintparts paintparts)
{
// the checkbox cell is disabled, so paint the border, background, and disabled checkbox for the cell.
if (!this.enabled)
{
// draw the cell background, if specified.
if ((paintparts & datagridviewpaintparts.background) == datagridviewpaintparts.background)
{
solidbrush cellbackground = new solidbrush(cellstyle.backcolor);
graphics.fillrectangle(cellbackground, cellbounds);
cellbackground.dispose();
}
// draw the cell borders, if specified.
if ((paintparts & datagridviewpaintparts.border) == datagridviewpaintparts.border)
{
paintborder(graphics, clipbounds, cellbounds, cellstyle, advancedborderstyle);
}
// calculate the area in which to draw the checkbox.
checkboxstate state = checkboxstate.mixeddisabled;
size size = checkboxrenderer.getglyphsize(graphics, state);
point center = new point(cellbounds.x, cellbounds.y);
center.x += (cellbounds.width - size.width) / 2;
center.y += (cellbounds.height - size.height) / 2;
// draw the disabled checkbox.
checkboxrenderer.drawcheckbox(graphics, center, state);
}
else
{
// the checkbox cell is enabled, so let the base class, handle the painting.
base.paint(graphics, clipbounds, cellbounds, rowindex, elementstate, value, formattedvalue, errortext, cellstyle, advancedborderstyle, paintparts);
}
}
}
public class datagridviewdisablecheckboxcolumn : datagridviewcheckboxcolumn
{
public datagridviewdisablecheckboxcolumn()
{
this.celltemplate = new datagridviewdisablecheckboxcell();
}
}
出處: 逍遙一生
本站主要提供各種技術文章,資源下載及圖片瀏覽等.
主要是要實現datagridviewdisablecheckboxcell的呈現方式,其中設定了checkboxstate的狀態為mixeddisabled,表示支援三種狀態,這個是實現效果的核心,如果要實現radiobutton列的效果,只需要將paint方法改成下面這樣即可:
protected override void paint(graphics graphics, rectangle clipbounds, rectangle cellbounds, int rowindex,
datagridviewelementstates elementstate, object value, object formattedvalue, string errortext,
datagridviewcellstyle cellstyle, datagridviewadvancedborderstyle advancedborderstyle, datagridviewpaintparts paintparts)
{
// draw the cell background, if specified.
if ((paintparts & datagridviewpaintparts.background) == datagridviewpaintparts.background)
{
solidbrush cellbackground = new solidbrush(cellstyle.backcolor);
graphics.fillrectangle(cellbackground, cellbounds);
cellbackground.dispose();
}
// draw the cell borders, if specified.
if ((paintparts & datagridviewpaintparts.border) == datagridviewpaintparts.border)
{
paintborder(graphics, clipbounds, cellbounds, cellstyle, advancedborderstyle);
}
// calculate the area in which to draw the checkbox.
radiobuttonstate state = value != null && (selectedstatus)value == selectedstatus.selected ? radiobuttonstate.checkednormal : radiobuttonstate.uncheckednormal;
size size = radiobuttonrenderer.getglyphsize(graphics, state);
point center = new point(cellbounds.x, cellbounds.y);
center.x += (cellbounds.width - size.width) / 2;
center.y += (cellbounds.height - size.height) / 2;
// draw the disabled checkbox.
radiobuttonrenderer.drawradiobutton(graphics, center, state);
}
使用radiobuttonstate代替checkboxstate。
當然,上面的代碼只是實現了列和儲存格的顯示效果,在使用過程中當使用者點擊單選或多選按鈕時如何改變狀態則需要自己手動編寫代碼來實現,如在點擊選項按鈕時將datagridview中其它行的選項按鈕設定為未選擇狀態,點擊多選按鈕時在三種狀態之間轉換等。
首先我們需要手動修改form的designer.cs檔案中的代碼,將checkbox所在的列的類型由datagridviewcheckboxcolumn改成datagridviewdisablecheckboxcolumn,並設定threestate的值為true,這個代碼是需要手動去修改的,因為預設情況下vs不支援對自訂datagridview列類型進行可視化編輯。要支援checkbox的三種狀態,我們還需要定義一個枚舉來給checkbox的truevalue、falsevalue和indeterminatevalue賦值。這個枚舉很簡單,有三個成員就夠了。
public enum selectedstatus
{
selected,
noselected,
indeterminate
}
然後設定checkbox的truevalue=selectedstatus.selected,falsevalue=selectedstatus.noselected,indeterminatevalue=selectedstatus.indeterminate。
好了!這個時候運行程式,可以看到經過我們改造的列已經可以正常顯示了,但是有一個問題,
那就是當我們點擊其中的單選或多選按鈕時它的狀態並不能發生變化,這是因為我們沒有在click事件中改變按鈕的選擇狀態。要實現這個功能,你需要給宿主datagridview定義cellcontentclick事件,並且判斷當使用者點擊的是否為你所指定的控制項,然後進行相應的處理。代碼如下:
private void datagridview1_cellcontentclick(object sender, datagridviewcelleventargs e)
{
if (e.rowindex >= 0)
{
datagridviewcolumn column = datagridview1.columns[e.columnindex];
if (column is datagridviewcheckboxcolumn)
{
datagridviewdisablecheckboxcell cell = datagridview1.rows[e.rowindex].cells[e.columnindex] as datagridviewdisablecheckboxcell;
if (!cell.enabled)
{
return;
}
if ((selectedstatus)cell.value == selectedstatus.noselected)
{
cell.value = selectedstatus.selected;
}
else if ((selectedstatus)cell.value == selectedstatus.selected)
{
cell.value = selectedstatus.indeterminate;
}
else
{
cell.value = selectedstatus.noselected;
}
}
}
}
這個是checkbox的,如果是radiobutton的話你還需要控制其它radionbutton的狀態,這個時候就沒有三種狀態而是兩種狀態了,代碼可以修改成這樣:
private void datagridview1_cellcontentclick(object sender, datagridviewcelleventargs e)
{
if (e.rowindex >= 0)
{
datagridviewcolumn column = datagridview1.columns[e.columnindex];
if (column is datagridviewcheckboxcolumn)
{
datagridviewdisablecheckboxcell cell = datagridview1.rows[e.rowindex].cells[e.columnindex] as datagridviewdisablecheckboxcell;
if (!cell.enabled)
{
return;
}
if ((selectedstatus)cell.value == selectedstatus.noselected)
{
cell.value = selectedstatus.selected;
setradiobuttonvalue(cell);
}
else
{
cell.value = selectedstatus.noselected;
}
}
}
}
private void setradiobuttonvalue(datagridviewdisablecheckboxcell cell)
{
selectedstatus status = (selectedstatus)cell.value;
if (status == selectedstatus.selected)
{
status = selectedstatus.noselected;
}
else
{
status = selectedstatus.selected;
}
for (int i = 0; i < datagridview1.rows.count; i++)
{
datagridviewdisablecheckboxcell cel = datagridview1.rows[i].cells["checkbox"] as datagridviewdisablecheckboxcell;
if (!cel.equals(cell))
{
cel.value = status;
}
}
}
函數setradionbuttonvalue負責修改宿主datagridview當前列中其它的radionbutton的狀態。
在完成這些工作後,一個相對完整的支援radionbutton或三種狀態的checkbox列的datagridview介面就完成了,你可以根據需要在接下來的代碼中來判斷datagridview中哪些行被選中了,或者哪些行處於未確定的選擇狀態(checkbox的第三種狀態),進而做出判斷來完成後面的工作。
最後我會提供整個工程供大家下載,其中也給出了datagridviewlinkcolumn列中的一些效果,如當滑鼠指向超連結時顯示一個tooltip,當使用者點擊超連結時開啟一個網頁等。