2010-06-08 4 views
5

D6 교수.Delphi - DBGrid에서 실제 행 복원

이전에는 DBISAM 및 DBISAMTable을 사용했습니다. 그것은 RecNo를 처리하고 수정 (삭제, 편집 등)과 함께 잘 작동합니다.

이제 우리는 RecNo를 처리하지 않는 ElevateDB로 교체했으며, 우리는 테이블이 아닌 쿼리를 사용합니다.

수정 사항을 보려면 쿼리를 다시 열어야합니다.

하지만 쿼리를 다시 열면 마지막 레코드로 재배치해야합니다. 격자가 다른 행에 표시되기 때문에 찾기가 충분하지 않습니다. 수정 기록이 다른 행으로 옮겨지면 그 행방을 따라 가기가 어렵고 사용자가이를 싫어하기 때문에 이것은 매우 혼란스러운 일입니다.

function TBaseDBGrid.GetActRow: integer; 
begin 
Result := -1 + Row; 
end; 


procedure TBasepDBGrid.SetActRow(aRow: integer); 
var 
bm : TBookMark; 
begin 
if IsDataSourceValid(DataSource) then with DataSource.DataSet do begin 
    bm := GetBookmark; 
    DisableControls; 
    try 
    MoveBy(-aRow); 
    MoveBy(aRow); 
    //GotoBookmark(bm); 
    finally 
    FreebookMark(bm); 
    EnableControls; 
    end; 
end; 
end; 

원래 예 moveby을 사용하는 것입니다 :

우리는이 코드를 발견했다. 이 쿼리는 백그라운드에서 쿼리가 다시 열리는 것을 볼 수 없기 때문에 시각적 컨트롤은 행 위치가 변경되지 않습니다.

그러나 EDBTable 또는 라이브/민감한 쿼리가있는 경우 MoveBy는 누군가를 삭제하거나 새 행을 추가하면 잘못된 레코드로 재배치 될 수 있으므로 사용하는 것은 위험합니다.

그런 다음 북마크를 사용하려고했습니다 (참고 자료 참조). 그러나이 기술은 다른 행 위치의 레코드를 보여주기 때문에 작동하지 않습니다 ...

그래서 질문 : DBGrid에서 행 위치와 레코드를 강제로 설정하는 방법은 무엇입니까?

또는 기본 DataSet을 새로 고친 후 레코드/행에 어떤 종류의 DBGrid를 재배치 할 수 있습니까?

DBGrid에서이 점프를 사용하려고했기 때문에 사용자 친화적 인 솔루션을 찾았습니다. 업데이트 후 원래 기록을 찾을 때 내 눈이 멀어지기 때문에 사용하기에 매우 좋지 않았습니다 ... :-(당신의 모든 도움, 링크 정보를

감사 : DD

답변

8

'MoveBy 's는 효과가 있기 때문에 사용하십시오.

데이터 세트를 닫기 전에 '북마크'를 가져 오십시오. 작업을하고 데이터 세트를 다시 연 다음 'MoveBy 's'를 사용하여 그리드에서 레코드의 위치를 ​​변경하십시오. 완료되면 다른 책갈피를 가져와 DataSet.CompareBookmarks를 사용하여 이전 책갈피와 비교하십시오. 결과가 0 인 경우, 0이 아닌 경우에만 이전 북마크에 대해 'GotoBookmark'를 발행하십시오.

이렇게하면 다른 사용자가 레코드를 삭제/삽입하지 않으면 그리드가 불안정 해 보이지 않을 것입니다. 그렇지 않은 경우 적어도 동일한 레코드를 사용하게됩니다.


편집 : 다음은 데이터 세트에서 삭제/삽입이 있던 경우에도 올바른 위치에 선택한 레코드의 위치를 ​​변경하는 코드 샘플입니다. 이 코드는 컨트롤을 비활성화/활성화하는 것을 생략하고 단순화를 위해 그리드를 채울 레코드가 적을 때 특별한 경우를 생략합니다.

type 
    TAccessDBGrid = class(TDBGrid); 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    BmSave, Bm: TBookmark; 
    GridRow, TotalRow: Integer; 
begin 
    GridRow := TAccessDBGrid(DBGrid1).Row; 
    TotalRow := TAccessDBGrid(DBGrid1).RowCount; 
    BmSave := DBGrid1.DataSource.DataSet.GetBookmark; 
    try 

    // close dataset, open dataset... 

    if DBGrid1.DataSource.DataSet.BookmarkValid(BmSave) then 
     DBGrid1.DataSource.DataSet.GotoBookmark(BmSave); 
    Dec(TotalRow); 
    if GridRow < TotalRow div 2 then begin 
     DBGrid1.DataSource.DataSet.MoveBy(TotalRow - GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(GridRow - TotalRow); 
    end else begin 
     if dgTitles in DBGrid1.Options then 
     Dec(GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(-GridRow); 
     DBGrid1.DataSource.DataSet.MoveBy(GridRow); 
    end; 
    Bm := DBGrid1.DataSource.DataSet.GetBookmark; 
    try 
     if (DBGrid1.DataSource.DataSet.BookmarkValid(Bm) and 
      DBGrid1.DataSource.DataSet.BookmarkValid(BmSave)) and 
      (DBGrid1.DataSource.DataSet.CompareBookmarks(Bm, BmSave) <> 0) then 
     DBGrid1.DataSource.DataSet.GotoBookmark(BmSave); 
    finally 
     DBGrid1.DataSource.DataSet.FreeBookmark(Bm); 
    end; 
    finally 
    DBGrid1.DataSource.DataSet.FreeBookmark(BmSave); 
    end; 
end; 
1

저장 후 기록에 다음 Locate을 쿼리를 닫고 재개하기 전에 고유 키 필드 (들)의 값 (들) 화면 갱신을 방지하기 위해 DisableControls/EnableControls.

+0

안녕하세요! 나는 그렇지 않습니다. GotoBookMark는 Open 이후에 있기 때문에 여기에서 Locate와 동일합니다. 그러나 실제 그리드 행은 동일하지 않으므로 그리드가 다른 위치에 레코드를 표시하지 않도록 설정하지 마십시오. MoveBy가 좋지만 여기에서 찾기가 필요합니다. 하지만 locate를 사용하면 그리드 행이 바뀌 었습니다 ... 예 : 그라인드에서 레코드 127이 네 번째 행에 표시됩니다. moveby로 다시 열면 네 번째 행에도 있습니다. Locate/Bookmark를 사용하면 3, 2, 5 - 무작위로 실제 레코드를 볼 수있는 곳 : ...-- ( – durumdara

+1

사용자 2 행을 삽입/삭제하면 사용자 1의 저장된 레코드 번호가 잘못됩니다. 이것이 TOndrej가 도우려고하는 것입니다 당신은 피 –

0

내 마음에 들어있는 코드의 단순한 조각 :

procedure DoRefresh(Dataset: TDataset); 
var 
    bkm: TBookmark; 
begin 
    Dataset.UpdateCursorPos; 
    bkm := Dataset.GetBookmark; 
    Dataset.DisableControls; 
    try 
    Dataset.Refresh; //refresh dataset if it's open 

    if Dataset.BookmarkValid(bkm) then 
    begin 
     Dataset.GotoBookmark(bkm); 
    end; 
    finally 
    Dataset.EnableControls; 
    Dataset.FreeBookmark(bkm); 
    end; 
end; 
+0

안녕 나는 다음과 같은 루틴을 사용합니다.! 이 aRow = Grid.GetRow(); Query.ReOpen, SetActRow (aRow) 그래서이 즐겨 찾기에 추가되지 않는 문제는,이 DBGrid를 행 문제입니다 ... – durumdara

+0

어떤 DBGrid를 사용하고 있습니까? Standard TDBGrid에는 GetRow 속성이 없습니다. DBGrid 문제인지 의심됩니다 .DBGrid ' 활성 레코드는 데이터 세트의 현재 활성 레코드입니다. – Linas

0

레코드 위치는 쿼리/테이블 개체에서 가져온 결과 집합의 정렬 순서에 따라 크게 달라집니다. 전혀 주문하지 않은 경우 서버에서 가져온 주문이 구현에 정의되어 있기 때문에 어떤 변경 사항이 발생하지 않았더라도 과 동일한 순서로 레코드가 제공된다는 보장을 할 수 없습니다.. 적어도 MSSQL과 Firebird에서는 주문 주문 절이 사용되지 않으면 다른 순서로 결과가 나옵니다.

재배치에 관해서는 TOndrej 솔루션이 가장 적합한 방법이라고 생각합니다. 결과 레코드의 기본 키를 사용하여 올바른 레코드에서 눈금을 다시 배치하십시오.