DGRid显示已选择但没有书签

时间:2013-04-05 20:27:35

标签: delphi delphi-5

刚刚发现了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]));

我该如何解决这个问题?

由于

2 个答案:

答案 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;

enter image description here