DataGridView绑定与详细说明

作者:袖梨 2022-06-25

datagridview绑定与详细说明

1、实现一个用于处理数据库教程数据检索的详细信息的方法。下面的代码示例实现一个 getdata 方法,该方法对一个 sqldataadapter 组件进行初始化,并使用该组件填充 datatable。然后,将 datatable 绑定到 bindingsource 组件。请确保将 connectionstring 变量的值设置为与数据库相应的值。
private void getdata(string selectcommand)
{
    try
    {
        string connectionstring =
            "integrated security=sspi;persist security info=false;" +
            "initial catalog=northwind;data source=localhost";
        dataadapter = new sqldataadapter(selectcommand, connectionstring);

        sqlcommandbuilder commandbuilder = new sqlcommandbuilder(dataadapter);

        datatable table = new datatable();
        table.locale = system.globalization.cultureinfo.invariantculture;
        dataadapter.fill(table);
        bindingsource1.datasource = table;

        datagridview1.autoresizecolumns(
            datagridviewautosizecolumnsmode.allcellsexceptheader);
    }
    catch (sqlexception)
    {
        messagebox.show("to run this example, replace the value of the " +
            "connectionstring variable with a connection string that is " +
            "valid for your system.");
    }
}
2、在窗体的 load 事件处理程序中,将 datagridview 控件绑定到 bindingsource 组件,并调用 getdata 方法从数据库中检索数据
private void form1_load(object sender, system.eventargs e)
{
    datagridview1.datasource = bindingsource1;
    getdata("select * from customers");
}


① 取得或者修改当前单元格的内容
② 设定单元格只读
③ 不显示最下面的新行
④ 判断新增行
⑤ 行的用户删除操作的自定义
⑥ 行、列的隐藏和删除
⑦ 禁止列或者行的resize
⑧ 列宽和行高以及列头的高度和行头的宽度的自动调整
⑨ 冻结列或行
⑩ 列顺序的调整
? 行头列头的单元格
? 剪切板的操作
? 单元格的tooltip的设置
? 右键菜单(contextmenustrip)的设置
? 单元格的边框、 网格线样式的设定
? 单元格表示值的设定
? 用户输入时,单元格输入值的设定
? 设定新加行的默认值

① datagridview  取得或者修改当前单元格的内容:

go to top

当前单元格指的是 datagridview 焦点所在的单元格,它可以通过 datagridview 对象的 currentcell 属性取得。如果当前单元格不存在的时候,返回nothing(c#是null)
[vb.net]
' 取得当前单元格内容
console.writeline(datagridview1.currentcell.value)
' 取得当前单元格的列 index
console.writeline(datagridview1.currentcell.columnindex)
' 取得当前单元格的行 index
console.writeline(datagridview1.currentcell.rowindex)

[c#]
// 取得当前单元格内容
console.writeline(datagridview1.currentcell.value);
// 取得当前单元格的列 index
console.writeline(datagridview1.currentcell.columnindex);
// 取得当前单元格的行 index
console.writeline(datagridview1.currentcell.rowindex);

另外,使用 datagridview.currentcelladdress 属性(而不是直接访问单元格)来确定单元格所在的行:datagridview.currentcelladdress.y 和列: datagridview.currentcelladdress.x 。这对于避免取消共享行的共享非常有用。

当前的单元格可以通过设定 datagridview 对象的 currentcell 来改变。可以通过 currentcell 来设定
datagridview 的激活单元格。将 currentcell 设为 nothing(null) 可以取消激活的单元格。

[vb.net]
' 设定 (0, 0)  为当前单元格
datagridview1.currentcell = datagridview1(0, 0)

[c#]
// 设定 (0, 0)  为当前单元格
datagridview1.currentcell = datagridview1[0, 0];
在整行选中模式开启时,你也可以通过 currentcell 来设定选定行。
        /**////


        /// 向下遍历
        ///

        ///
        ///
        private void button4_click(object sender, eventargs e)
        ...{
            int row = this.datagridview1.currentrow.index + 1;
            if (row > this.datagridview1.rowcount - 1)
                row = 0;
            this.datagridview1.currentcell = this.datagridview1[0, row]; 
        }

        /**////


        /// 向上遍历
        ///

        ///
        ///
        private void button5_click(object sender, eventargs e)
        ...{
            int row = this.datagridview1.currentrow.index - 1;
            if (row < 0)
                row = this.datagridview1.rowcount - 1;
            this.datagridview1.currentcell = this.datagridview1[0, row]; 
        }
* 注意: this.datagridview 的索引器的参数是: columnindex, rowindex 或是 columnname, rowindex
这与习惯不同。


--------------------------------------------------------------------------------
② datagridview  设定单元格只读:

go to top

1) 使用 readonly 属性
→ 如果希望,datagridview 内所有单元格都不可编辑, 那么只要:
[vb.net]
' 设置 datagridview1 为只读
datagridview1.readonly = true
[c#]
// 设置 datagridview1 为只读
datagridview1.readonly = true;此时,用户的新增行操作和删除行操作也被屏蔽了。

→ 如果希望,datagridview 内某个单元格不可编辑, 那么只要:
[vb.net]
' 设置 datagridview1 的第2列整列单元格为只读
datagridview1.columns(1).readonly = true

' 设置 datagridview1 的第3行整行单元格为只读
datagridview1.rows(2).readonly = true

' 设置 datagridview1 的[0,0]单元格为只读
datagridview1(0, 0).readonly = true
[c#]
// 设置 datagridview1 的第2列整列单元格为只读
datagridview1.columns[1].readonly = true;

// 设置 datagridview1 的第3行整行单元格为只读
datagridview1.rows[2].readonly = true;

// 设置 datagridview1 的[0,0]单元格为只读
datagridview1[0, 0].readonly = true;
2) 使用 editmode 属性
datagridview.editmode 属性被设置为 datagridvieweditmode.editprogrammatically 时,用户就不能手动编辑单元格的内容了。但是可以通过程序,调用 datagridview.beginedit 方法,使单元格进入编辑模式进行编辑。
[vb.net]
datagridview1.editmode = datagridvieweditmode.editprogrammatically
[c#]
datagridview1.editmode = datagridvieweditmode.editprogrammatically;
3) 根据条件设定单元格的不可编辑状态
当一个一个的通过单元格坐标设定单元格 readonly 属性的方法太麻烦的时候,你可以通过 cellbeginedit 事件来取消单元格的编辑。
[vb.net]
'cellbeginedit 事件处理方法
private sub datagridview1_cellbeginedit(byval sender as object, _
        byval e as datagridviewcellcanceleventargs) _
        handles datagridview1.cellbeginedit
    dim dgv as datagridview = ctype(sender, datagridview)
    ' 是否可以进行编辑的条件检查
    if dgv.columns(e.columnindex).name = "column1" andalso _
        not cbool(dgv("column2", e.rowindex).value) then
        ' 取消编辑
        e.cancel = true
    end if
end sub
[c#]
// cellbeginedit 事件处理方法
private void datagridview1_cellbeginedit(object sender,
    datagridviewcellcanceleventargs e)
{
    datagridview dgv = (datagridview)sender;
    //是否可以进行编辑的条件检查
    if (dgv.columns[e.columnindex].name == "column1" &&
        !(bool)dgv["column2", e.rowindex].value)
    {
        // 取消编辑
        e.cancel = true;
    }
}

--------------------------------------------------------------------------------
③ datagridview  不显示最下面的新行:

go to top

通常 datagridview 的最下面一行是用户新追加的行(行头显示 * )。如果不想让用户新追加行即不想显示该新行,可以将 datagridview 对象的 allowusertoaddrows 属性设置为 false。
[vb.net]
' 设置用户不能手动给 datagridview1 添加新行
datagridview1.allowusertoaddrows = false
[c#]
// 设置用户不能手动给 datagridview1 添加新行
datagridview1.allowusertoaddrows = false;
但是,可以通过程序: datagridviewrowcollection.add 为 datagridview 追加新行。

补足: 如果 datagridview 的 datasource 绑定的是 dataview, 还可以通过设置 dataview.allowadd
属性为 false 来达到同样的效果。


--------------------------------------------------------------------------------
④ datagridview  判断新增行:

go to top

datagridview的allowusertoaddrows属性为true时也就是允许用户追加新行的场合下,datagridview的最后一行就是新追加的行(*行)。使用 datagridviewrow.isnewrow 属性可以判断哪一行是新追加的行。另外,通过datagridview.newrowindex 可以获取新行的行序列号。在没有新行的时候,newrowindex = -1。 [vb.net]
if datagridview1.currentrow.isnewrow then
    console.writeline("当前行为新追加行。")
else
    console.writeline("当前行不是新追加行。")
end if

--------------------------------------------------------------------------------
⑤ datagridview  行的用户删除操作的自定义:

go to top

1) 无条件的限制行删除操作。
默认时,datagridview 是允许用户进行行的删除操作的。如果设置 datagridview对象的allowusertodeleterows属性为 false 时, 用户的行删除操作就被禁止了。
[vb.net]
' 禁止datagridview1的行删除操作。
datagridview1.allowusertodeleterows = false
[c#]
// 禁止datagridview1的行删除操作。
datagridview1.allowusertodeleterows = false;
但是,通过 datagridviewrowcollection.remove 还是可以进行行的删除。
补足: 如果 datagridview 绑定的是 dataview 的话,通过 dataview.allowdelete 也可以控制行的删除。

2) 行删除时的条件判断处理。
用户在删除行的时候,将会引发 datagridview.userdeletingrow 事件。 在这个事件里,可以判断条件并取消删除操作。
[vb.net]
' datagridview1 的 userdeletingrow 事件
private sub datagridview1_userdeletingrow(byval sender as object, _
        byval e as datagridviewrowcanceleventargs) _
        handles datagridview1.userdeletingrow
    '  删除前的用户确认。
    if messagebox.show("确认要删除该行数据吗?", "删除确认", _
        messageboxbuttons.okcancel, messageboxicon.question) <> _
            windows.forms.dialogresult.ok then
        '  如果不是 ok,则取消。
        e.cancel = true
    end if
end sub
[c#]
// datagridview1 的 userdeletingrow 事件
private void datagridview1_userdeletingrow(
    object sender, datagridviewrowcanceleventargs e)
{
    // 删除前的用户确认。
    if (messagebox.show("确认要删除该行数据吗?", "删除确认",
        messageboxbuttons.okcancel,
        messageboxicon.question) != dialogresult.ok)
    {
        // 如果不是 ok,则取消。
        e.cancel = true;
    }
}

--------------------------------------------------------------------------------
⑥ datagridview  行、列的隐藏和删除:

go to top

1) 行、列的隐藏
[vb.net]
' datagridview1的第一列隐藏
datagridview1.columns(0).visible = false
' datagridview1的第一行隐藏
datagridview1.rows(0).visible = false
[c#]
// datagridview1的第一列隐藏
datagridview1.columns[0].visible = false;
// datagridview1的第一行隐藏
datagridview1.rows[0].visible = false;
2) 行头、列头的隐藏
[vb.net]
' 列头隐藏
datagridview1.columnheadersvisible = false
' 行头隐藏
datagridview1.rowheadersvisible = false
[c#]
// 列头隐藏
datagridview1.columnheadersvisible = false;
// 行头隐藏
datagridview1.rowheadersvisible = false;
3) 行和列的删除
[vb.net]
' 删除名为"column1"的列
datagridview1.columns.remove("column1")
' 删除第一列
datagridview1.columns.removeat(0)
' 删除第一行
datagridview1.rows.removeat(0)

[c#]
' 删除名为"column1"的列
datagridview1.columns.remove("column1");
' 删除第一列
datagridview1.columns.removeat(0);
' 删除第一行
datagridview1.rows.removeat(0);
4) 删除选中行
[vb.net]
for each r as datagridviewrow in datagridview1.selectedrows
    if not r.isnewrow then
        datagridview1.rows.remove(r)
    end if
next
[c#]
foreach (datagridviewrow r in datagridview1.selectedrows)
{
    if (!r.isnewrow)
    {
        datagridview1.rows.remove(r);
    }
}

--------------------------------------------------------------------------------
⑦ datagridview 禁止列或者行的resize:

go to top

1) 禁止所有的列或者行的resize
[vb.net]
' 禁止用户改变datagridview1的所有列的列宽
datagridview1.allowusertoresizecolumns = false

'禁止用户改变datagridview1の所有行的行高
datagridview1.allowusertoresizerows = false
[c#]
// 禁止用户改变datagridview1的所有列的列宽
datagridview1.allowusertoresizecolumns = false;

//禁止用户改变datagridview1の所有行的行高
datagridview1.allowusertoresizerows = false;
但是可以通过 datagridviewcolumn.width 或者 datagridviewrow.height 属性设定列宽和行高。

2) 禁止指定行或者列的resize
[vb.net]
'  禁止用户改变datagridview1的第一列的列宽
datagridview1.columns(0).resizable = datagridviewtristate.false

'  禁止用户改变datagridview1的第一列的行宽
datagridview1.rows(0).resizable = datagridviewtristate.false
[c#]
// 禁止用户改变datagridview1的第一列的列宽
datagridview1.columns[0].resizable = datagridviewtristate.false;

// 禁止用户改变datagridview1的第一列的行宽
datagridview1.rows[0].resizable = datagridviewtristate.false;
→ 关于 noset

当 resizable 属性设为 datagridviewtristate.notset 时, 实际上会默认以 datagridview 的 allowusertoresizecolumns 和  allowusertoresizerows 的属性值进行设定。比如: datagridview.allowusertoresizecolumns = false 且 resizable 是 noset 设定时,resizable = false 。


判断 resizable 是否是继承设定了 datagridview 的 allowusertoresizecolumns 和  allowusertoresizerows 的属性值, 可以根据 state 属性判断。如果 state 属性含有 resizableset,那么说明没有继承设定。


3) 列宽和行高的最小值的设定
[vb.net]
' 第一列的最小列宽设定为 100
datagridview1.columns(0).minimum

' 第一行的最小行高设定为 50
datagridview1.rows(0).minimum
[c#]
// 第一列的最小列宽设定为 100
datagridview1.columns[0].minimum;

// 第一行的最小行高设定为 50
datagridview1.rows[0].minimum;
4) 禁止用户改变行头的宽度以及列头的高度
[vb.net]
'  禁止用户改变列头的高度
datagridview1.columnheadersheightsizemode = _
    datagridviewcolumnheadersheightsizemode.disableresizing

' 禁止用户改变行头的宽度
datagridview1.rowheaderswidthsizemode = _
    datagridviewrowheaderswidthsizemode.enableresizing
[c#]
// 禁止用户改变列头的高度
datagridview1.columnheadersheightsizemode =
    datagridviewcolumnheadersheightsizemode.disableresizing;

// 禁止用户改变行头的宽度
datagridview1.rowheaderswidthsizemode =
    datagridviewrowheaderswidthsizemode.enableresizing;


--------------------------------------------------------------------------------
⑧ datagridview 列宽和行高自动调整的设定:
go to top

1) 设定行高和列宽自动调整
[vb.net]
' 设定包括header和所有单元格的列宽自动调整
datagridview1.autosizecolumnsmode = datagridviewautosizecolumnsmode.allcells

' 设定包括header和所有单元格的行高自动调整
datagridview1.autosizerowsmode = datagridviewautosizerowsmode.allcells
[c#]
// 设定包括header和所有单元格的列宽自动调整
datagridview1.autosizecolumnsmode = datagridviewautosizecolumnsmode.allcells;

// 设定包括header和所有单元格的行高自动调整
datagridview1.autosizerowsmode = datagridviewautosizerowsmode.allcells;
autosizecolumnsmode 属性的设定值枚举请参照 msdn 的 datagridviewautosizerowsmode 说明。

2)指定列或行自动调整
[vb.net]
'  第一列自动调整
datagridview1.columns(0).autosizemode = _
    datagridviewautosizecolumnmode.displayedcells
[c#]
// 第一列自动调整
datagridview1.columns[0].autosizemode =
    datagridviewautosizecolumnmode.displayedcells;
autosizemode 设定为 notset  时, 默认继承的是  datagridview.autosizecolumnsmode 属性。

3) 设定列头的高度和行头的宽度自动调整 [vb.net]
'  设定列头的宽度可以自由调整
datagridview1.columnheadersheightsizemode = _
    datagridviewcolumnheadersheightsizemode.autosize

'  设定行头的宽度可以自由调整
datagridview1.rowheaderswidthsizemode = _
    datagridviewrowheaderswidthsizemode.autosizetoallheaders
[c#]
// 设定列头的宽度可以自由调整
datagridview1.columnheadersheightsizemode =
    datagridviewcolumnheadersheightsizemode.autosize;

// 设定行头的宽度可以自由调整
datagridview1.rowheaderswidthsizemode =
    datagridviewrowheaderswidthsizemode.autosizetoallheaders;
4) 随时自动调整
a, 临时的,让列宽自动调整,这和指定autosizecolumnsmode属性一样。 [vb.net]
' 让 datagridview1 的所有列宽自动调整一下。
datagridview1.autoresizecolumns(datagridviewautosizecolumnsmode.allcells)

' 让 datagridview1 的第一列的列宽自动调整一下。
datagridview1.autoresizecolumn(0, datagridviewautosizecolumnmode.allcells)
[c#]
// 让 datagridview1 的所有列宽自动调整一下。
datagridview1.autoresizecolumns(datagridviewautosizecolumnsmode.allcells);

// 让 datagridview1 的第一列的列宽自动调整一下。
datagridview1.autoresizecolumn(0, datagridviewautosizecolumnmode.allcells);上面调用的 autoresizecolumns 和 autoresizecolumn 当指定的是datagridviewautosizecolumnmode.allcells 的时候, 参数可以省略。即:
datagridview1.autoresizecolumn(0) 和 datagridview1.autoresizecolumns()

b,临时的,让行高自动调整
[vb.net]
' 让 datagridview1 的所有行高自动调整一下。
datagridview1.autoresizerows(datagridviewautosizerowsmode.allcells)

' 让 datagridview1 的第一行的行高自动调整一下。
datagridview1.autoresizerow(0, datagridviewautosizerowmode.allcells)
[c#]
// 让 datagridview1 的所有行高自动调整一下。
datagridview1.autoresizerows(datagridviewautosizerowsmode.allcells);

//让 datagridview1 的第一行的行高自动调整一下。
datagridview1.autoresizerow(0, datagridviewautosizerowmode.allcells);上面调用的 autoresizerows 和 autoresizerow 当指定的是datagridviewautosizerowmode.allcells 的时候, 参数可以省略。即:datagridview1.autoresizerow (0) 和 datagridview1.autoresizerows()

c,临时的,让行头和列头自动调整
[vb.net]
' 列头高度自动调整
datagridview1.autoresizecolumnheadersheight()

' 行头宽度自动调整
datagridview1.autoresizerowheaderswidth( _
    datagridviewrowheaderswidthsizemode.autosizetoallheaders)
[c#]
// 列头高度自动调整
datagridview1.autoresizecolumnheadersheight();

// 行头宽度自动调整
datagridview1.autoresizerowheaderswidth(
    datagridviewrowheaderswidthsizemode.autosizetoallheaders);
关于性能:
通过 autosizecolumnsmode 或者 autosizerowsmode 属性所指定的单元格进行自动调整时,如果调整次数过于多那么将可能导致性能下降,尤其是在行和列数比较多的情况下。在这时用 displayedcells 代替 allcells 能减少非所见的单元格的调整,从而提高性能。


--------------------------------------------------------------------------------
⑨ datagridview 冻结列或行
go to top

1) 列冻结
datagridviewcolumn.frozen 属性为 true 时, 该列左侧的所有列被固定, 横向滚动时固定列不随滚动条滚动而左右移动。这对于重要列固定显示很有用。
 

[vb.net]
' datagridview1的左侧2列固定
datagridview1.columns(1).frozen = true
 

[c#]
// datagridview1的左侧2列固定
datagridview1.columns[1].frozen = true;
但是,datagridview.allowusertoordercolumns = true 时,固定列不能移动到非固定列, 反之亦然。

2) 行冻结
datagridviewrow.frozen 属性为 true 时, 该行上面的所有行被固定, 纵向滚动时固定行不随滚动条滚动而上下移动。
[vb.net]
' datagridview1 的上3行固定
datagridview1.rows(2).frozen = true
[c#]
// datagridview1 的上3行固定
datagridview1.rows[2].frozen = true;


--------------------------------------------------------------------------------
⑩ datagridview 列顺序的调整

go to top

设定 datagridview 的 allowusertoordercolumns 为 true 的时候, 用户可以自由调整列的顺序。
当用户改变列的顺序的时候,其本身的 index 不会改变,但是 displayindex 改变了。你也可以通过程序改变 displayindex 来改变列的顺序。 列顺序发生改变时会引发 columndisplayindexchanged 事件:
[vb.net]
' datagridview1的columndisplayindexchanged事件处理方法
private sub datagridview1_columndisplayindexchanged(byval sender as object, _
        byval e as datagridviewcolumneventargs) _
        handles datagridview1.columndisplayindexchanged
    console.writeline("{0} 的位置改变到 {1} 。", _
        e.column.name, e.column.displayindex)
end sub
[c#]
// datagridview1的columndisplayindexchanged事件处理方法
private void datagridview1_columndisplayindexchanged(object sender,
    datagridviewcolumneventargs e)
{
    console.writeline("{0} 的位置改变到 {1} ",
        e.column.name, e.column.displayindex);
}

--------------------------------------------------------------------------------
? datagridview 行头列头的单元格

go to top


[vb.net]
' datagridview1的第一列列头内容
datagridview1.columns(0).headercell.value = "第一列"

' datagridview1的第一行行头内容
datagridview1.rows(0).headercell.value = "第一行"

' datagridview1的左上头部单元内容
datagridview1.topleftheadercell.value = "左上"
[c#]
// 改变datagridview1的第一列列头内容
datagridview1.columns[0].headercell.value = "第一列";

// 改变datagridview1的第一行行头内容
datagridview1.rows[0].headercell.value = "第一行";

// 改变datagridview1的左上头部单元内容
datagridview1.topleftheadercell.value = "左上";
另外你也可以通过 headertext 来改变他们的内容。
[vb.net]
' 改变datagridview1的第一列列头内容
datagridview1.columns(0).headertext = "第一列"
[c#]
// 改变datagridview1的第一列列头内容
datagridview1.columns[0].headertext = "第一列";

--------------------------------------------------------------------------------
? datagridview 剪切板的操作

go to top
datagridview.clipboardcopymode 属性被设定为 datagridviewclipboardcopymode.disable 以外的情况时,「ctrl + c」 按下的时候,被选择的单元格的内容会拷贝到系统剪切板内。格式有: text, unicodetext,html, commaseparatedvalue。可以直接粘贴到 excel 内。

clipboardcopymode 还可以设定 header部分是否拷贝: enablealwaysincludeheadertext 拷贝header部分、enablewithoutheadertext 则不拷贝。默认是 enablewithautoheadertext , header 如果选择了的话,就拷贝。

1) 编程方式实现剪切板的拷贝

clipboard.setdataobject(datagridview1.getclipboardcontent())

2) datagridview 的数据粘贴

实现剪切板的拷贝比较容易,但是实现 datagridview 的直接粘贴就比较难了。「ctrl + v」按下进行粘贴时,datagridview 没有提供方法,只能自己实现。

以下,是粘贴时简单的事例代码,将拷贝数据粘贴到以选择单元格开始的区域内。
[vb.net]
' 当前单元格是否选择的判断
if datagridview1.currentcell is nothing then
    return
end if
dim insertrowindex as integer = datagridview1.currentcell.rowindex

' 获取剪切板的内容,并按行分割
dim pastetext as string = clipboard.gettext()
if string.isnullorempty(pastetext) then
    return
end if
pastetext = pastetext.replace(vbcrlf, vblf)
pastetext = pastetext.replace(vbcr, vblf)
pastetext.trimend(new char() {vblf})
dim lines as string() = pastetext.split(vblf)

dim isheader as boolean = true
for each line as string in lines
    ' 是否是列头
    if isheader then
        isheader = false
    else
        ' 按 tab 分割数据
        dim vals as string() = line.split(controlchars.tab)
        ' 判断列数是否统一

相关文章

精彩推荐