[delphi-users:2190] Re:Re:ClientDataSet1.GotoBookmark(pointer(DBGrid1.SelectedRows[0]))で「レコードが見つかりません」例外が発生する

147 views
Skip to first unread message

moru

unread,
Sep 9, 2011, 6:41:55 PM9/9/11
to delphi...@freeml.com
お世話様です。
その後の経過を報告します。
この問題については、インデックスを張ったフィールドの値を変更する場面では、値の変更前にあらかじめ主キーとなる値を配列に取得しておき、その値を元にFindKeyしながら値の変更処理を実行するようにしました。
これで解決とさせていただきますが、もし対応方法ご存じの方いらっしゃればお願いします。

再現ソースを本文に書いていましたが、共有ファイルへもあげました。
ボタン1、ボタン2の順でClickすると再現します。
http://www.freeml.com/delphi-users/file/249105

MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
友達の服をこっそり借りちゃお!「おしゃれ泥棒」
http://ad.freeml.com/cgi-bin/sa.cgi?id=hnTz1
-----------------------------------------------------[freeml by GMO]--

ありい

unread,
Sep 9, 2011, 9:08:21 PM9/9/11
to delphi...@freeml.com
 moruさん、こんにちは。

 Button2のイベントの

> ClientDataSet1.GotoBookmark(pointer(DBGrid1.SelectedRows[0]));

...を、

DBGrid1.SelectedRows.Refresh; // ←この行を追加
ClientDataSet1.GotoBookmark(pointer(DBGrid1.SelectedRows[0]));

...とすると如何でしょう?

ありい


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
戦国時代の武将達とともに天下統一を目指そう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hnVbI

moru

unread,
Sep 10, 2011, 2:17:56 AM9/10/11
to delphi...@freeml.com
ありい様、ありがとうございます。
試したところ、値の変更が発生した行だけ選択が解除されるようです。
これですと少し期待する動作とは違います。選択されたままになってほしいです。
 
ヘルプにあるとおり、「Refresh メソッドは,無効なブックマークを Items 配列から削除します。」ということなのかと思います。
VCLのソースを見ようとしましたが、ソースがないため(Delphi7)調べられませんが、IndexもSelectedRowsもTBookmarkListを利用していてIndexを張った列の値を変えるとTBookmarkListから外れてしまうのかなという感じがしました。
稲庭

2011年9月10日10:08 ありい <delphi...@freeml.com>:

ありい

unread,
Sep 11, 2011, 7:46:56 PM9/11/11
to delphi...@freeml.com
 moruさん、おはようございます。

> 試したところ、値の変更が発生した行だけ選択が解除されるようです。
> これですと少し期待する動作とは違います。選択されたままになってほしいです。

 なるほど。軽く整理させてください。

 例えば、1~10までの10行があった場合に、2~4の
3行がグリッド上、選択されていたとします。

 で、その後、仮に3行目の3が903に変更された場合は、
グリッド上は1,2,4...10,903という順番になると
思います。

#フィールド'int'にはインデックスが設定されていますから。

 その時に、moruさんが期待されている状態は、

1)2,4,5が選択されている

2)2,4,903が選択されている

...の、1の状態で大丈夫でしょうか?

 そして現状、

> DBGrid1.SelectedRows.Refresh; // ←この行を追加

 を挟むと、4の行の選択が外れてしまう、ということです
よね。

 問題は、DBGridで行を選択 → 行の値を変更 とすると、
DBGridで保持している選択Bookmarkが古くなり利用できなく
なってしまうことですね。

 すると少し強引な手になりますが...

 Pr_nBookmarkPos: integer をprivateに定義して、

1)CDSのBeforeEditで選択されているレコードの位置を把握する
2)CDSのAfterPostで選択されているレコードが変更されたら、再度
  選択しなおす(Bookmarkを更新する)

 ...これで少しは近付けると良いのですが。

#削除のことは考えていません(^^; 良くテストしてみて下さいね。

ありい

procedure TForm1.ClientDataSet1BeforeEdit(DataSet: TDataSet);
var
bs: TBookmarkStr;
i: integer;
begin
Pr_nBookmarkPos := -1;
bs := DataSet.Bookmark;
if DBGrid1.SelectedRows.Find(bs, i) then begin
// グリッド選択されいてるレコード番号を記録
Pr_nBookmarkPos := DataSet.RecNo;
//Pr_nBookmarkPos := i;
end;
end;

procedure TForm1.ClientDataSet1AfterPost(DataSet: TDataSet);
var
nDef: integer;
begin
nDef := DataSet.RecNo;
try
if Pr_nBookmarkPos > 0 then begin
// グリッド選択されているレコードのPOST
DBGrid1.SelectedRows.Refresh; // 一旦DBGrid1のブックマークを綺麗に
DataSet.RecNo := Pr_nBookmarkPos; // 元レコードに移動
DBGrid1.SelectedRows.CurrentRowSelected := true; // 選択ブックマークに追加
end;

finally
DataSet.RecNo := nDef;
end;
end;


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
使い方はいろいろ♪一部のメンバーだけにMLメールを送ろう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hpuAQ

moru

unread,
Sep 13, 2011, 5:02:17 PM9/13/11
to delphi...@freeml.com

ありい様、ありがとうございます。
返信遅くなりすみません。
また、ソースまで提示いただいてありがとうございます。

>#フィールド'int'にはインデックスが設定されていますから。
サンプルソースがよくありませんでしたが、もし並び順を制御するフィールドがフィールド'int'よりも1つ前にある場合、並び順は変わりませんがBookmarkは無効になってしまうという状況です。(CloneCursorしても同じ問題にあたります)

しかし、SelectedRows.Refresh;してからもう一度範囲選択するようにしてみます。
これで範囲選択を保持してほしいケースはカバーできそうです。
ありがとうございました。
稲庭
 
2011年9月12日8:46 ありい <delphi...@freeml.com>:

ありい

unread,
Sep 14, 2011, 7:34:03 AM9/14/11
to delphi...@freeml.com
 moruさん、こんばんは。

> もし並び順を制御するフィールドがフィールド'int'よりも1つ前にある場合、
> 並び順は変わ りませんがBookmarkは無効になってしまうという状況です。
> (CloneCursorしても同じ問題にあたります)

 そうですね。ソートが有効・無効に関わらず、選択 → 変更の順で、その行の
Bookmarkが無効になります。

 整理させて頂いたのは、もし前メールの2)を期待されている場合には、少し
コードが変わってくるので確認させて頂きました。

> しかし、SelectedRows.Refresh;してからもう一度範囲選択するようにして み
> ます。
> これで範囲選択を保持してほしいケースはカバーできそうです。

 そう思います(^^)

#単純にDBGridの複数行選択が、選択されている行番号だけ押さえていてくれて
いれば、こんな苦労しなくて良いのに...と思いました(^^;

ありい


MLホームページ: http://www.freeml.com/delphi-users

----------------------------------------------------------------------
使い方はいろいろ♪一部のメンバーだけにMLメールを送ろう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=hqbii

Reply all
Reply to author
Forward
0 new messages