Previous topicNext topic
Help > 开发指南 > 预备知识 >
如何引用行

如何正确引用行关系到我们如何处理数据,所以这里我们来介绍一下在我们平台中如何在各种场景下引用行数据。

首先我们要知道我们平台中有哪些行,以及它们之间的转换关系。

1、Row:全路径为C1.Win.C1FlexGrid.Row。属于SmGrid.Rows下的项。可以通过扩展方法Row.GetRowData()来获得RowData对象。

2、DataRow:全路径为System.Data.DataRow。属于DataTable.Rows下的项。这里也可以通过扩展方法DataRow.GetRowData()来获得RowData对象。

3、RowData:全路径为sanMuSoft.Data.RowData。属于DataTableHelp.DataRows下的项。可以通过RowData.BaseRow属性来获得DataRow对象。

根据上面的已知条件,我们几乎可以做到几个对象之间互相引用了,唯一不能做到的就是根据RowData获得Row对象。在正常的场景中我们是用不到这个功能的,唯一的例外就是在目录树表(SmEditTreeGrid)中,我们有时候会需要用到通过RowData来获得对应的Row对象。

在SmEditTreeGrid中我们可以通过SmEditTreeGrid.GetRowFromRowData(RowData)方法来获得对应的Row对象。

获取行的方法

1、CurrentRowData。RowData类型,我们可以通过此属性来返回SmGrid、SmEditTreeGrid、IDataRuelGrid对象的当前行。结合之前学习的“如何引用表”中学到的,我们可以通过Proj.CurrentGrid.CurrentRowData来访问当前表的当前行。

 Vb.Net
Dim dr As RowData=Proj.CurrentGrid.CurrentRowData

C#
RowData dr = Proj.CurrentGrid.CurrentRowData;

2、遍历表的选择区域

 Vb.Net
'先定义变量获取表
Dim tbl As SmGrid = Proj.CurrentSmGrid
tbl.StopRedraw()
'获取当前表的当前选择区域
Dim rng As CellRange = tbl.Selection

Try
    '遍历选择区域的每一列
    For j As Integer = rng.c1 To rng.c2
        '如果当前列允许编辑并且没有禁用当前表中编辑
        If tbl.Cols(j).AllowEditing AndAlso Not tbl.View.ViewCols(tbl.Cols(j).Name).OnlyDisableEditInGrid Then
            '遍历选择区域的每一行
            For i As Integer = rng.r1 To rng.r2
                '如果指定行没有绑定数据或者当前行没有被锁定,则继续清除操作
                If tbl.Rows(i).GetRowData() Is Nothing OrElse Not tbl.Rows(i).GetRowData().Locked Then
                    '将指定单元格赋值为空,即消除数据
                    tbl.SetData(i, j, DBNull.Value)
                End If
            Next
        End If
    Next
    
Catch ex As Exception
    UnhandledExceptionManager.ShowAndSaveLog(ex)
Finally
    tbl.ResumeRedraw()
End Try

C#
//先定义变量获取表
SmGrid tbl=Proj.CurrentSmGrid;
tbl.StopRedraw();
//获取当前表的当前选择区域
CellRange rng = tbl.Selection;
try
{
    //遍历选择区域的每一列
    for (int j = rng.c1; j <= rng.c2; j++)
    {
        //如果当前列允许编辑并且没有禁用当前表中编辑
        if (tbl.Cols[j].AllowEditing && !tbl.View.ViewCols[tbl.Cols[j].Name].OnlyDisableEditInGrid)
        {
            //遍历选择区域的每一行
            for (int i = rng.r1; i <= rng.r2; i++)
            {
                //如果指定行没有绑定数据或者当前行没有被锁定,则继续清除操作
                if (tbl.Rows[i].GetRowData()==null || !tbl.Rows[i].GetRowData().Locked)
                {
                    //将指定单元格赋值为空,即消除数据
                    tbl.SetData(i, j, DBNull.Value);
                }
            }
        }
    }
}
catch (Exception ex)
{
    UnhandledExceptionManager.ShowAndSaveLog(ex);
}
finally
{
    tbl.ResumeRedraw();
}

3、遍历当前表中所有行。如果我们表中没有任何的节点、合计行、新增行、分类汇总等等其他数据,我们也可以通过SmGrid.Rows来遍历所有行

 VB.Net
Dim tbl As SmGrid=Proj.CurrentSmGrid
'遍历表中所有行
For Each dr As RowData In tbl.View.ViewRows
    '给ID字段赋值
    dr("ID")=Sys.NewGUID
Next
'根据行对象进行循环遍历
For Each tr As Row In tbl.Rows
    '如果当前的行有绑定数据
    If tr.DataIndex>=0 Then
        tr("ID")=Sys.NewGUID
    End If
Next
'根据行号进行遍历
If tbl.HaveUserRow>0 Then '有用户数据,指除了合计行、新增行、标题行外还有数据行
    'tbl.Rows.Fixed指的是标题行的行数,tbl.Rows.Fixed可以指代数据行的开始序号
    For i As Integer = tbl.Rows.Fixed To tbl.Rows.Count-1
        '如果当前的行有绑定数据
        If tbl.Rows(i).DataIndex>=0 Then
            tbl.Rows(i)("ID")=Sys.NewGUID
        End If
    Next
End If

 C#
SmGrid tbl = Proj.CurrentSmGrid;
// 遍历表中所有行
foreach (RowData dr in tbl.View.ViewRows)
{
    // 给ID字段赋值
    dr["ID"] = Sys.NewGUID;
}
// 根据行对象进行循环遍历
foreach (Row tr in tbl.Rows)
{
    //如果当前的行有绑定数据
    if (tr.DataIndex >= 0)
    {
        tr["ID"] = Sys.NewGUID;
    }
}
// 根据行号进行遍历
if (tbl.HaveUserRow > 0) //有用户数据,指除了合计行、新增行、标题行外还有数据行
{
    //tbl.Rows.Fixed指的是标题行的行数,tbl.Rows.Fixed可以指代数据行的开始序号
    for (int i = tbl.Rows.Fixed; i <= tbl.Rows.Count - 1; i++)
    {
        //如果当前的行有绑定数据
        if (tbl.Rows(i).DataIndex >= 0)
        {
            tbl.Rows(i)["ID"] = Sys.NewGUID;
        }
    }
}

4、遍历当前表中筛选后的数据

 Vb.Net
'先定义变量获取表
Dim tbl As SmGrid = Proj.CurrentSmGrid
'循环遍历
For Each dr As RowData In tbl.View.ViewRows
    dr("ID")=Sys.NewGUID
Next

'按序号来遍历
For i As Integer = 0 To tbl.View.ViewRows.Count-1
    '根据序号来获得行的引用
    Dim dr As RowData=tbl.View.ViewRows(i)
    dr("ID")=Sys.NewGUID
Next

C#
// 先定义变量获取表
SmGrid tbl = Proj.CurrentSmGrid;
// 循环遍历
foreach (RowData dr in tbl.View.ViewRows)
    dr["ID"] = Sys.NewGUID;

// 按序号来遍历
for (int i = 0; i <= tbl.View.ViewRows.Count - 1; i++)
{
    // 根据序号来获得行的引用
    RowData dr = tbl.View.ViewRows[i];
    dr["ID"] = Sys.NewGUID;
}

5、遍历当前表绑定的所有数据

 Vb.Net
'先定义变量获取表
Dim tbl As SmGrid = Proj.CurrentSmGrid
'循环遍历
For Each dr As RowData In tbl.DataTableHelp.DataRows
    dr("ID")=Sys.NewGUID
Next
'按序号遍历
For i As Integer = 0 To tbl.DataTableHelp.DataRows.Count-1
    Dim dr As RowData=tbl.DataTableHelp.DataRows(i)
    dr("ID")=Sys.NewGUID
Next

C#
// 先定义变量获取表
SmGrid tbl = Proj.CurrentSmGrid;
// 循环遍历
foreach (RowData dr in tbl.DataTableHelp.DataRows)
{
    dr["ID"] = Sys.NewGUID;
}
    
// 按序号遍历
for (int i = 0; i <= tbl.DataTableHelp.DataRows.Count - 1; i++)
{
    RowData dr = tbl.DataTableHelp.DataRows[i];
    dr("ID") = Sys.NewGUID;
}

6、在事件中获取当前行。有三种情况,

第一种是我们通过e参数可以获得相应单元格的e.Row和e.Col,注意这里的Row和Col是整数型的,表示BaseGrid的行序号和列序号。

第二种是我们通过e参数可以获得相应e.RowData和e.ColData,这两个是引用对象,我们可以直接引用。

第三种是我们什么参数也没有,只能通过将sender转化成表,然后通过上面提到的CurrentRowData属性来获得当前行。

 Vb.Net
        Public Sub ColDataChanged(sender As Object,e As sanMuSoft.CS.WinForm.ColDataEventArgs)
            '根据事件触发对象获得表对象
            Dim tbl As SmGrid=sender
            
            '根据ColData对象获得列名称
            Dim strColName=e.ColData.Name
            '根据列名称获得Column对象
            Dim col As Column=tbl.Cols(strColName)
            '根据e参数ColData直接获得ColData对象
            Dim dc As ColData=e.ColData
            '根据列名称获得ViewCol对象
            Dim vc As ViewCol=tbl.View.ViewCols(strColName)
            '根据e参数的RowData直接获得RowData对象
            Dim dr As RowData=e.RowData
            '根据RowData对象的BaseRow属性,返回DataRow对象
            Dim ddr As DataRow=e.RowData.BaseRow
            '根据e.RowData属性获得当前行
            Dim curr As RowData=e.RowData
        End Sub 
        Public Sub KeyPressEdit(sender As Object,e As C1.Win.C1FlexGrid.KeyPressEditEventArgs)
            '根据事件触发对象获得表对象
            Dim tbl As SmGrid=sender
            '根据列序号获得Column对象
            Dim col As Column=tbl.Cols(e.Col)
            '根据Col对象获得列名称
            Dim strColName=tbl.Cols(e.Col).Name
            '根据列名称获得ColData对象
            Dim dc As ColData=tbl.DataTableHelp.DataCols(strColName)
            '根据列名称获得ViewCol对象
            Dim vc As ViewCol=tbl.View.ViewCols(strColName)
            '根据行序号获得Row对象
            Dim tr As Row=tbl.Rows(e.Row)
            '根据Row对象获得RowData对象,注意如果当前行为非绑定行,则返回空对象
            Dim dr As RowData=tbl.Rows(e.Row).GetRowData()
            '根据RowData对象的BaseRow属性,返回DataRow对象
            Dim ddr As DataRow=tbl.Rows(e.Row).GetRowData().BaseRow
            '根据CurrentRowData属性获得当前行
            Dim curr As RowData=tbl.CurrentRowData
        End Sub

C#
    public void ColDataChanged(object sender, sanMuSoft.CS.WinForm.ColDataEventArgs e)
    {
        // 根据事件触发对象获得表对象
        SmGrid tbl = sender;

        // 根据ColData对象获得列名称
        var strColName = e.ColData.Name;
        // 根据列名称获得Column对象
        Column col = tbl.Cols[strColName];
        // 根据e参数ColData直接获得ColData对象
        ColData dc = e.ColData;
        // 根据列名称获得ViewCol对象
        ViewCol vc = tbl.View.ViewCols[strColName];
        // 根据e参数的RowData直接获得RowData对象
        RowData dr = e.RowData;
        // 根据RowData对象的BaseRow属性,返回DataRow对象
        DataRow ddr = e.RowData.BaseRow;
        // 根据e.RowData属性获得当前行
        RowData curr = e.RowData;
    }
    public void KeyPressEdit(object sender, C1.Win.C1FlexGrid.KeyPressEditEventArgs e)
    {
        // 根据事件触发对象获得表对象
        SmGrid tbl = sender;
        // 根据列序号获得Column对象
        Column col = tbl.Cols[e.Col];
        // 根据Col对象获得列名称
        var strColName = tbl.Cols[e.Col].Name;
        // 根据列名称获得ColData对象
        ColData dc = tbl.DataTableHelp.DataCols[strColName];
        // 根据列名称获得ViewCol对象
        ViewCol vc = tbl.View.ViewCols[strColName];
        // 根据行序号获得Row对象
        Row tr = tbl.Rows[e.Row];
        // 根据Row对象获得RowData对象,注意如果当前行为非绑定行,则返回空对象
        RowData dr = tbl.Rows[e.Row].GetRowData();
        // 根据RowData对象的BaseRow属性,返回DataRow对象
        DataRow ddr = tbl.Rows[e.Row].GetRowData().BaseRow;
        // 根据CurrentRowData属性获得当前行
        RowData curr = tbl.CurrentRowData;
    }

7、这里再加一个比较典型的循环遍历选择区域删除行的示例。

Vb.Net
'先定义变量获取表
Dim tbl As SmGrid = Proj.CurrentSmGrid
'如果不让删除,则直接退出
If tbl.AllowDelete AndAlso tbl.Selection.IsValid Then
    tbl.StopRedraw()
    '获取当前表的当前选择区域
    Dim rng As CellRange = tbl.Selection
    
    Try
        '由于删除动作会影响tb.Selection.r2这样的值,所以必须先在循环之前将这个值赋值到变量中
        Dim intLast As Integer = tbl.Selection.r2
        Dim intFirst As Integer = tbl.Selection.r1
        '遍历选择区域的每一行,因为删除操作会影响DataRows集合,为了不让删除影响序列的指定关系,我们从最后一行往前面反过来遍历
        For i As Integer = intLast To intFirst
            '如果指定行有绑定数据并且当前行没有被锁定,则继续删除操作
            If tbl.Rows(i).GetRowData() IsNot Nothing AndAlso Not tbl.Rows(i).GetRowData().Locked Then
                '将指定行删除
                tbl.Rows(i).GetRowData().Delete()
            End If
        Next
    Catch ex As Exception
        UnhandledExceptionManager.ShowAndSaveLog(ex)
    Finally
        tbl.ResumeRedraw()
    End Try
End If

C#
//先定义变量获取表
SmGrid tbl=Proj.CurrentSmGrid;
//如果不让删除,则直接退出
if(tbl.AllowDelete && tbl.Selection.IsValid)
{
    tbl.StopRedraw();
    //获取当前表的当前选择区域
    CellRange rng = tbl.Selection;
    try
    {
        //由于删除动作会影响tb.Selection.r2这样的值,所以必须先在循环之前将这个值赋值到变量中
        int intLast = tbl.Selection.r2;
        int intFirst = tbl.Selection.r1;
        //遍历选择区域的每一行,因为删除操作会影响DataRows集合,为了不让删除影响序列的指定关系,我们从最后一行往前面反过来遍历
        for (int i = intLast; i >= intFirst; i--)
        {
            //如果指定行有绑定数据并且当前行没有被锁定,则继续删除操作
            if (tbl.Rows[i].GetRowData()!=null && !tbl.Rows[i].GetRowData().Locked)
            {
                //将指定行删除
                tbl.Rows[i].GetRowData().Delete();
            }
        }
    }
    catch (Exception ex)
    {
        UnhandledExceptionManager.ShowAndSaveLog(ex);
    }
    finally
    {
        tbl.ResumeRedraw();
    }
}