【问题标题】:DGRid showing Selected but no BookmarkDGRid 显示已选择但没有书签
【发布时间】:2013-04-05 20:27:35
【问题描述】:

刚刚发现 D5 和/或 Zeos 的怪异之处。我有一个 TDBgrid 和 DataSet。

我有一个“删除”功能来删除选定的 DBGrid 行。

如果我 Ctlr-Left-click 以选择 Row(或 Rows),一切正常,但是...

如果我使用垂直滚动条滑块移动到数据集的顶部,那么它会以所选颜色显示第一行。

如果点击顶行,(它看起来已经被选中)然后点击“删除”它会崩溃。单步执行代码,在第一行 SelectedRows.Count 显示“1”,然后在书签行出现“找不到书签错误”如果我在使用滑块后首先单击已选择的行,则不会崩溃.

for i:=0 to dbgridAddr.SelectedRows.Count-1 do
begin
  dbgridAddr.DataSource.DataSet.GotoBookmark(pointer(dbgridAddr.SelectedRows.Items[i]));

我该如何解决这个问题?

谢谢

【问题讨论】:

  • 看起来你在做一些非常丑陋的事情。书签确实是指针,也许 dbGrid.SelectedRows 是转换为指针的有效方法,但在事件处理期间这样做可能不是原子的或安全的。
  • @warren Ugly casts 与否,直接来自 Delphi 帮助示例!不能太丑:)
  • 是的,我想我忘记了 Datasets 中的书签有多严重。
  • @user2220358:你在我的回答中看到更新了吗?

标签: delphi delphi-5


【解决方案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

【讨论】:

    【解决方案2】:

    德尔福 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);
    

    例如考虑一个包含 10 个项目的列表。

    whatEver = 0 .. 9

    如果我们现在在“for 循环”中使用 i = 1 执行 whatEver.delete(i);

    这样我们就删除了第二项。

    现在whatEver 只是0 .. 8

    循环初始化为通过0 to 9 运行。现在您可以了解i = 9 是否使用whatEver.delete(i); 尝试在0 .. 8 之外访问whatEver 这会导致错误。

    另一个例子。

    您删除了不正确的记录。

    我们会假设。
    之前,您已经确定了以下项目(数据记录) - 要删除的编号。

    #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的什么事件?

    测试没有选择,只有滚动。

    关闭您的应用并重新启动,只滚动 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;
    

    【讨论】:

    • @miskito 感谢您的详细回复,但我不会在那个阶段删除或更改数据集,我只是使用滚动条滑块移动 view数据集在顶部显示第一个项目,它会自动被视觉选择。您描述的测试与我在调试模式下单步执行时在 OP 中提到的完全相同。 “SelectedRows.Count 显示为“1”,这是突出显示的第一行。但是,即使它被突出显示/选中,也没有设置书签。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-15
    相关资源
    最近更新 更多