刚刚发现了D5和/或Zeos的怪异。我有一个TDBgrid和DataSet。
我有一个“删除”功能来删除DBGrid的选定行。
如果我Ctlr-左键单击以选择行(或行),它一切正常,但是......
如果我使用Vertical Scrollbar滑块移动到DataSet的顶部,那么它会显示选择颜色的第一行。
如果不,请点击顶行(已经看起来已选中),然后点击“删除”它会崩溃。单步执行代码,在第一行SelectedRows.Count显示“1”但在Bookmark行我得到“未找到书签错误”如果我在使用滑块后首先点击已经选择的行,那么这不会崩溃
for i:=0 to dbgridAddr.SelectedRows.Count-1 do
begin
dbgridAddr.DataSource.DataSet.GotoBookmark(pointer(dbgridAddr.SelectedRows.Items[i]));
我该如何解决这个问题?
由于
答案 0 :(得分:1)
我想回答有点晚了,但也许其他人会觉得它很有用。问题是,当您在 DbGrid 的边界内单击时,即使不是 ,也会显示为选定行。
将此添加到您的 DBGrid 的 OnDrawColumnCell 事件处理程序:
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
// Only highlight the row if it is actually selected
if TDBGrid(Sender).SelectedRows.CurrentRowSelected then
begin
TDBGrid(Sender).Canvas.Brush.Color := clHighlight;
TDBGrid(Sender).Canvas.Font.Style := Font.Style + [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clHighlightText;
end
else
begin
TDBGrid(Sender).Canvas.Brush.Color := clBtnFace;
TDBGrid(Sender).Canvas.Font.Style := Font.Style - [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clWindowText;
end;
// Commit drawing
TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
如果您希望在使用箭头键时能够看到网格中的光标位置,请添加这样的块
else if (gdSelected in State) then
begin
TDBGrid(Sender).Canvas.Brush.Color := clBtnFace;
TDBGrid(Sender).Canvas.Font.Style := Font.Style + [fsBold];
TDBGrid(Sender).Canvas.Font.Color := clWindowText;
end
答案 1 :(得分:0)
Delphi 5:
您写道:
if I use the Vertical Scrollbar slider to move to the top of the DataSet then it shows the first Row in the select color.
即使看起来那样。这并不意味着它也被评估为标记。
您可以使用以下方法进行测试:
if dbgridAddr.SelectedRows.CurrentRowSelected then
ShowMessage('selected') else
ShowMessage('NOT selected');
从数据集中删除记录时,不会自动从列表中删除位置标记。
因此,某些位置标记可能无效。
dbgridAddr.SelectedRows.Refresh;
刷新以确保列表仅包含有效条目。
刷新尝试查找数据集中所有在Items属性数组中显示为位置标记的记录。
将删除所有数据量不相等的位置标记。
如果位置标记无效,则Refresh返回值True
并使DBGrid对象无效,以便触发重绘,在这种情况下,将删除所有无效记录。
如果列表中的所有位置标记都有效,则Refresh返回值False
。
永远不要删除具有此结构的列表中的项目。
for i:=0 to whatEver.Count-1 do
whatEver.delete(i);
e.g。考虑一个包含10个项目的列表。
whatEver = 0 .. 9
如果我们现在处于“for循环”,i = 1
执行whatEver.delete(i);
,
这样我们就删除第二项。
现在whatEver
仅为0 .. 8
。
循环初始化为0 to 9
。现在,您可以了解i = 9
然后whatEver.delete(i);
是否尝试在whatEver
之外访问0 .. 8
这会导致错误。
另一个例子。
删除不正确的记录。
我们假设。
之前 lopp你已经确定了以下项目(数据记录) - 要删除的数字。
#3 , #6 , #8
for i:=0 to whatEver.Count-1 do
if (i=3) OR (i=6) OR (i=8) then whatEver.delete(i);
如果i=3
,则执行whatEver.delete(3);
之后
第4行现在是第3行 第5行现在是第4行 第6行现在是第5行 等等
现在
if... OR (i=6) then whatEver.delete(6);
删除错误的项目,前一行7!
书签指针也指#6,没有刷新。
请不要立即发布it is better to compare the content
。
for i:=0 to whatEver.Count-1 do
if (whatEver[i] = 'blue') OR (whatEver[i] = 'green') OR (whatEver[i] = 'red')
then whatEver.delete(i);
I know that, it's just an example to show what happens when you delete items from the sequence out.
以这种方式做得更好:
for i:= whatEver.Count-1 downto 0 do
whatEver.delete(i);
因此它从删除开始。较低的项目保持其有效性。
修改强>
我不知道您正在使用的DBGrid是什么事件?
要测试没有选择,只能使用滚动。
关闭你的App并重新启动,不做任何事情只滚动DBGrid
不要点击进入DBGrid !!
然后按下你的测试按钮。
procedure TForm1.Button2Click(Sender: TObject);
begin
if DBGrid1.SelectedRows.CurrentRowSelected then
begin
ShowMessage('selected');
end else begin
if DBGrid1.SelectedRows.Count>0 then
ShowMessage(' CurrentRow NOT selected'+#13#10+
'A part in your code must have select another row.')
else
ShowMessage('NOT selected');
end;
end;