我在CFormView中放置了datagrid控件,但没有和数据库绑定。
然后我动态设置了5列,初始化了列的caption。
但是当我想在表格中添加数据时就出现了问题:
比如我想在第一行第一列中设置一个字符串:
  GetRow()总是返回-1;
   SetRow()提示rowset invalid;
   这是什么原因啊?怎么向表格中动态添加数据,怎么设置表格为可编辑状态?   拜托了。

解决方案 »

  1.   

    需要可以编辑的好像应该用msflexgrid
    可以通过
    setrow(..)
    settext(..)
      

  2.   

    建一个空的Recordset和它绑定(在程序中运行时绑定)
      

  3.   

    我正在用DBGrid,但是用的是和ADO绑定的方式,在网上找到这篇文章,没自己研究过,贴出来给大家看看:在无绑定模式下使用DBGrid作者:Adrian Roman     翻译:白鹤    我花了好长时间来注意这件事情,因为我不能在其他任何文件中找到关于
    DBGrid 在无绑定模式下的VC++编程内容(只有VB的)。我想把我的心得与别人
    分享会是一个好主意。    首先,尽管连随机文档都说它能接受任何类型的变量作为书签,但是好象并不
    是那么回事儿。DaoRecordset把SAFEARRAY作为书签(GetBook返回包含
    VT_ARRAY | VT_UI1的变量),但它不能与DBGrid一起工作(DBGrid把变量转变
    为VT_BSTR)。 它可能会与VT_I4工作的很好,但据说字符串是最好的,所以我
    用他们。当然,我把书签转换成字符串再转换回来。 SchedQ是一个通过查询得
    来的动态集(CDaoRecordset),如果关于他你有任何bug或是好想法,请跟我分
    享您的发现。 啊,对,我几乎忘了!极其重要!如果你从OCX的类库中继承了
    RowBuffer类,请修改构造函数,原构造函数得到LPDISPACH作为参数去调用基类
    的构造函数,这时第二个参数要设为FALSE(原来隐性地设置为TRUE)。如果不
    这样做,当RowBuffer对象被消除时整个程序会崩溃。 补充技巧:记着使用
    BeforeColUpdate 和KeyPress事件去验证一个域的输入及相应地过滤键盘的输入。   请不要给我来e-mails,问我关于如何在绑定模式下使用他们的问题。在加入
    DBGrid之前加上一个Microsoft Remote Data Control 的对话框,然后花点时
    间调整一下它的属性,你就会弄明白如何使用它。 致那些想在运行时改变列
    的人:由DBGrid类生成的GetColumns()成员函数是一个真正的GetColumn函数
    (返回一个指向单个列的LPDISPATCH---这样你就可以用这个LPDISPATCH来构造
    单个列对象,而不是列集的对象)。如果你想获得指向列集的LPDISPATCH,
    把GetColumns()该名为GetColumn,然后象下面这样重新写一个GetColumns():
    LPDISPATCH CMsDgridCtrl::GetColumns()
    {
    LPDISPATCH result;
    InvokeHelper(0x8,DISPATCH_PROPERTYGET,VT_DISPATCH,(void*)&result,NULL,NULL);
    return result;
    } 
      这样你就可以用返回的LPDISPATCH来构造列集对象。 那么现在,往网格中输
    入数据、删除纪录、当网格中写操作发生时从网格中获取数据的代码如下所示:
    void CMyView::OnUnboundReadDataDbgridMy(LPDISPATCH RowBuf, VARIANT FAR* StartLocation, BOOL ReadPriorRows) {
    // TODO: Add your control notification handler code here
    RowBuffer buf(RowBuf); 
    VARIANT varbok;
    varbok.vt=VT_ARRAY | VT_UI1;
    long Row,RowsFetched;
    VARIANT var;
    RowsFetched=0;
    if(StartLocation->vt==VT_NULL){
    if(ReadPriorRows){
    try{
    SchedQ->MoveLast();
    }catch(CDaoException* e){
    e->Delete();
    }
    }else{
    try{
    SchedQ->MoveFirst();
    }catch(CDaoException* e){
    e->Delete();
    }
    }
    }else{
    //根据StartLocation书签和ReadPriorRows参数找到开始读数据的位置

    try{
    VectorFromBstr(StartLocation->bstrVal,&varbok.parray);
    SchedQ->SetBook(COleVariant(varbok));
    if(ReadPriorRows)SchedQ->MovePrev();
    else SchedQ->MoveNext();
    }catch(CDaoException* e){
    e->Delete();
    }
    }
    //把我们的数据集数组转换为DBGrid 用来显示数据的RowBuf对象,
    for(Row = 0; RowIsEOF() || SchedQ->IsBOF())break;
    var.vt=VT_I4;
    var.lVal=SchedQ->m_WorkCodeID;
    if(buf.GetColumnCount()>0)buf.SetValue(Row, 0,var);
    COleVariant olvi(SchedQ->m_TimeIn);
    var=*((LPVARIANT)olvi);
    if(buf.GetColumnCount()>1)buf.SetValue(Row, 1,var);
    COleVariant olvo(SchedQ->m_TimeOut);
    var=*((LPVARIANT)olvo);
    if(buf.GetColumnCount()>2)buf.SetValue(Row, 2,var);
    // Set book using CurRow which is also our
    // array index
    var.vt=VT_BSTR;
    BstrFromVector(((LPVARIANT)SchedQ->GetBook())->parray,&var.bstrVal);
    buf.SetBook(Row,var);
    RowsFetched++;
    if(ReadPriorRows)SchedQ->MovePrev();
    else SchedQ->MoveNext();
    }
    buf.SetRowCount(RowsFetched);

    void CMyView::OnUnboundWriteDataDbgridMy(LPDISPATCH RowBuf, VARIANT FAR* WriteLocation)
    {
    // TODO: Add your control notification handler code here
    RowBuffer buf(RowBuf);
    VARIANT varbok;
    varbok.vt=VT_ARRAY | VT_UI1;
    COleVariant var;
    CString str;
    try{
    VectorFromBstr(WriteLocation->bstrVal,&varbok.parray);
    SchedQ->SetBook(COleVariant(varbok));
    }catch(CDaoException* e){
    e->Delete();
    buf.SetRowCount(0);
    return;
    }
     
    //**********************************************************************
    //Here was a portion of code that validated the record
     
    //************************************************

    //只有被修改过的列更新,否则,值被设置为NULL
    try{
    SchedQ->Edit();
    }
    catch(CDaoException* e){
    e->Delete();
    buf.SetRowCount(0);
    return;

    if(buf.GetValue(0L, 0).vt!=VT_NULL){
    var=buf.GetValue(0, 0);
    str=CString(var.bstrVal);
    SchedQ->m_WorkCodeID=atol(str);
    }
    if(buf.GetValue(0L, 1).vt!=VT_NULL){
    var=buf.GetValue(0, 1);
    str=CString(var.bstrVal);
    SchedQ->m_TimeIn.ParseDateTime(str);
    }
    if(buf.GetValue(0L, 2).vt!=VT_NULL){
    var=buf.GetValue(0, 2);
    str=CString(var.bstrVal);
    SchedQ->m_TimeOut.ParseDateTime(str);
    }
    try{
    SchedQ->Update();
    }catch(CDaoException *e){
    SchedQ->CancelUpdate();
    e->Delete();
    buf.SetRowCount(0);
    }
    }
    void CMyView::OnUnboundAddDataDbgridMy(LPDISPATCH RowBuf, VARIANT FAR* NewRowBook) 
    {
    // TODO: Add your control notification handler code here
    RowBuffer buf(RowBuf);
    COleVariant var;
    CString str;
    NewRowBook->vt=VT_NULL;
     
    //**********************************************************************
    //Here was a portion of code that validated the record
    //**********************************************************************
    try{
    SchedQ->AddNew();
    SchedQ->Update();
    SchedQ->SetBook(SchedQ->GetLastModifiedBook());
    SchedQ->Edit();
    }catch(CDaoException* e){
    e->Delete();
    buf.SetRowCount(0);
    return;

    SchedQ->m_EmployeeID=m_pSet->m_EmployeeID;
    try{
    if(buf.GetValue(0L, 0).vt!=VT_NULL){ 
    var=buf.GetValue(0, 0);
    }else{
    var.vt=VT_I4; 
    var.lVal=0;
    Column col(m_SchedGrid.GetColumns(var));
    var=col.GetDefaultValue();
    }
    str=(char*)_bstr_t(var.bstrVal);
    SchedQ->m_WorkCodeID=atol(str);
    if(buf.GetValue(0L, 1).vt!=VT_NULL){
    var=buf.GetValue(0, 1);
    }else{
    var.vt=VT_I4; 
    var.lVal=1;
    Column col(m_SchedGrid.GetColumns(var));
    var=col.GetDefaultValue();
    }
    str=(char*)_bstr_t(var.bstrVal);
    SchedQ->m_TimeIn.ParseDateTime(str);
    if(buf.GetValue(0L, 2).vt!=VT_NULL){
    var=buf.GetValue(0, 2);
    }else{
    var.vt=VT_I4; 
    var.lVal=2;
    Column col(m_SchedGrid.GetColumns(var));
    var=col.GetDefaultValue();
    }
    str=(char*)_bstr_t(var.bstrVal);
    SchedQ->m_TimeOut.ParseDateTime(str);
    var.vt=VT_I4;
    SchedQ->Update();
    }catch(CDaoException *e){
    e->Delete();
    SchedQ->CancelUpdate();
    SchedQ->Delete();
    buf.SetRowCount(0);
    }
    NewRowBook->vt=VT_BSTR;
    BstrFromVector(((LPVARIANT)SchedQ->GetBook())->parray,&(NewRowBook->bstrVal));

    void CMyView::OnUnboundDeleteRowDbgridMy(VARIANT FAR* Book) 
    {
    // TODO: Add your control notification handler code here
    VARIANT varbok;
    varbok.vt=VT_ARRAY | VT_UI1;
    VectorFromBstr(Book->bstrVal,&varbok.parray);
    try{
    SchedQ->SetBook(COleVariant(varbok));
    SchedQ->Delete();
    }catch(CDaoException* e){
    Book->vt=VT_NULL;
    e->Delete();

    } 
      

  4.   

    我是这么绑定的://    _RecordsetPtr m_pRS;
    //    m_gridView和DBGrid空间关联
        m_pRS.CreateInstance( __uuidof(Recordset)); 
        CString strConnection( _T("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Data.mdb"));    try 
    {     
    m_pRS->CursorLocation = adUseClient;
                      m_pRS->Open(_T("SELECT * FROM Data"), _bstr_t(strConnection), adOpenKeyset,adLockOptimistic, adCmdText);
    }
    catch (_com_error &e)
    {
    AfxMessageBox( (LPCTSTR)e.Description());
    }

    m_gridView.SetRefDataSource(NULL);
    m_gridView.SetRefDataSource( (LPUNKNOWN) m_pRS );
    m_gridView.Refresh();
    DBGrid本身支持数据的修改什么,就像Access一样。
    如果你不和数据库关联还是用MSFlexGrid吧
      

  5.   


    谢谢你的资料和解答。有个问题:MSFlexGrid 好像不支持在网格中编辑吧。
      

  6.   

    谢谢FishBones() 的资料和解答还有个问题:FlexGrid好像不支持在网格中编辑,只能用编程实现添加.
      

  7.   

    我用一个空的Recordset和他绑定:
       _Recordset rs;
    rs.CreateInstance("ADODB.Recordset");
    m_grid.SetrefDataSource(NULL);
    m_grid.SetrefDataSource(rs);
    m_grid.Refresh();
    int rows=m_grid.GetRow();结果:rows等于-1;
    m_grid.setrow(1);// erroe: recordset invalid.
    还是不行啊~是不是要完全用recordset才能在datagrid control中显示数据啊?(太惨了~~~)
    有没有简单的方法在网格控件中显示数据和编辑数据啊?
    谁能帮忙,谢谢了。
      

  8.   

    怎么实现想access中那样的实时编辑呢
      

  9.   

    DBGrid直接和打开数据库的Recordset绑定,应该可以编辑了,除非你把字段设为不可编辑或锁定