DBGrid 停止当前行移动

2023-12-14

使用 d5、TDBGrid、SQLite3 和 ZEOS。数据库有 2000 个项目,一列是“Active”布尔值,第二列是“ItemName”文本,IndexFiledNames 是“ItemName”

OnDblclick 切换“活动”开/关,并且一切按预期工作Data。 Active 从 True 变为 False,然后再返回。

但是,如果我双击 DBGrid 的最后一个可见行,以切换活动状态 - 切换后,DBGrid 将该项目行移动到网格的垂直中心行位置。对于刚刚双击跳跃的行的用户来说,这非常令人困惑。

如何阻止网格将该行移动到中间?最后的所有项目都会发生这种情况可见行DGBGrid 的。

{编辑}重新删除的项目是减少问题的尝试 - 没有成功。

procedure TfrmMain.dbgridItemsDblClick(Sender: TObject);
begin
  puItemsSelectedClick(Self);
end;

procedure TfrmMain.puItemsSelectedClick(Sender: TObject);
//var
//  CurrItem : String;
//  CurrIndx : String;
begin
  if dm.tblItems.RecordCount = 0 then
  begin
    myShowMsg('There are no Items in the Items List');
    Exit;
  end;
//  CurrItem:=dm.tblItems.FieldByName(fldItemGroupShop).AsString;
//  CurrIndx:=dm.tblItems.IndexFieldNames;
  dm.tblItems.DisableControls;
  try
//    dm.tblItems.IndexFieldNames:='';
    dm.tblItems.Edit;
    dm.tblItems.FieldByName(fldSelected).AsBoolean:=
      not(dm.tblItems.FieldByName(fldSelected).AsBoolean);
    dm.tblItems.Post;
//    dm.tblItems.IndexFieldNames:=CurrIndx;
//    dm.tblItems.Locate(fldItemGroupShop,CurrItem,[]);
  finally
    dm.tblItems.EnableControls;
  end;
end;

DBGrid的当前行号和显示行数是受保护的属性, 所以你需要在代码中添加一个“classcracker”类型声明,如下所示:

type
  TMyDBGrid = Class(TDBGrid);

function TForm1.GetGridRow: Integer;
begin
  Result := TmyDBGrid(DBGrid1).Row;
end;

function TForm1.GridRowCount : Integer;
begin
  Result := TmyDBGrid(DBGrid1).RowCount;
end;

完成此操作后,在表单上放置一个 TEdit 和 TButton 以输入小于当前行号的新网格行号。然后尝试以下例程:

procedure TForm1.SetGridRow(NewRow : Integer);
var
  GridRows,
  OldRow,
  MoveDataSetBy,
  MovedBy : Integer;
  DataSet : TDataSet;
  Possible : Boolean;
  ScrollUp : Boolean;
begin
  OldRow := GetGridRow;
  if NewRow = OldRow then
    Exit;

  ScrollUp := NewRow < OldRow;

  DataSet := dBGrid1.DataSource.DataSet;

  GridRows := TmyDBGrid(DBGrid1).RowCount;
  { TODO : Test the case where the DataSet doesn't have enough rows to fill the grid}
  { TODO : Check why grid reports one more row than it displays.
   Meanwhile ... }
  GridRows := GridRows - 1;

  // First check whether the NewRow value is sensible
  Possible := (NewRow >= 1) and (NewRow <= GridRows);
  if not Possible then exit;

  try
    if ScrollUp then begin

    //  First scroll the dataset forwards enough to bring
    //  a number of new records into view
    MoveDataSetBy := GridRows - NewRow;
    MovedBy := DataSet.MoveBy(MoveDataSetBy);
    Shortfall := MoveDataSetBy - MovedBy;
    if Shortfall = 0 then begin
      //  Now scroll the dataset backwards to get back
      //  to the record we were on
      MoveDataSetBy := -GridRows + NewRow;
      MovedBy := DataSet.MoveBy(MoveDataSetBy);
    end
    else
      MovedBy := DataSet.MoveBy(-MovedBy);
  end
  else begin
    MoveDataSetBy :=  -(NewRow - 1);
    MovedBy := DataSet.MoveBy(MoveDataSetBy);
    //  We need to know if the DS cursor was able to move far enough
    //  back as we've asked or was prevented by reaching BOF
    Shortfall := MoveDataSetBy - MovedBy;
    if Shortfall = 0 then begin
      // The DS cursor succeeded on moving the requested distance
      MoveDataSetBy := NewRow - 1;
      MovedBy := DataSet.MoveBy(MoveDataSetBy);
    end
    else
      //  it failed, so we need to return to the record we started on
      //  but this won't necessarily return us the same grid row number
      MovedBy := DataSet.MoveBy(-MovedBy);
    finally
      DBGrid1.Invalidate;
    end;

我之前的建议是通过“Tma DBGrid(DBGrid).Row := NewRow;”直接分配给网格行是基于错误的记忆,因为事实上这似乎没有什么用处。

由于我们不依赖于有意义的 RecNo,因此“if ScrollUp”之后的算法变得复杂。这涉及到检查数据集光标是否可以沿该方向移动足够的量opposite我们想要将网格行移入,以相对于网格中的行滚动 DS 光标,而不点击 EOF 或 BOF - 如果发生其中任何一种,我们只需将 DS 光标移回原来的位置并放弃尝试滚动网格。

对于ScrollUp,逻辑是:

  • 首先将数据集光标移动到网格中的最后一行
  • 然后根据新旧 Row 值之间的差异将其向前移动一些。
  • 然后将其向后移动,移动量等于网格中的行数减去新行值。

如果一切成功,当前行将移动到 NewRow 值所请求的网格位置。 当然,该代码结合了前两个步骤。起初,我认为这段代码是无意义的,因为用于 DataSet.MoveBy()s 的值的代数和为零。实际上, 这不是废话,只是有点违反直觉。当然,距离加起来为零,因为我们想回到我们曾经的记录;执行 DataSet.MoveBy() 的目的就是要松开网格对当前记录的控制,然后返回到它。顺便说一句,这就是为什么在移出当前记录然后返回到它时没有必要执行我通常的操作,即 DataSet.GetBookmark/GotBookmark/FreeBookmark ,并且实际上使用这些会破坏代码的预期效果。

顺便说一句,我使用的是 ClientDataSet,而不是 ZEOS,但这应该没有任何区别。

顺便说一句,本地 DataSet 变量用于访问网格的数据集,而不使用 Delphi 的地狱般的“With ...”构造。

顺便说一句,您对“Rows div 2”的评论提醒了我:我不认为网格告诉数据集,ISTR它是与网格关联的数据链接,它告诉数据集应该为多少记录分配缓冲区。然后,在 TDataSet.Resync 中,您会注意到

if rmCenter in Mode then
  Count := (FBufferCount - 1) div 2 else
  Count := FActiveRecord;

然后看看后面例程中Count是如何使用的;你的理论可能是正确的。也许在“if cmCenter in Mode”上放置一个断点,看看它是否从网格运行的地方被调用。

顺便说一句#2,即使这段代码没有帮助,这篇文章可能会有所帮助http://delphi.about.com/od/usedbvcl/l/aa011004a.htm

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

DBGrid 停止当前行移动 的相关文章

随机推荐

  • 如何将矩形传递到 pygame.display.update() 中以更新窗口的特定区域?

    On the 文档页 for pygame display update 它表示您可以将一个矩形传递到该方法中以更新部分屏幕 然而 我看到的所有示例都只是从程序中的图像或形状传递现有的矩形 我如何告诉它直接更新屏幕上的某个区域 例如 当绘制
  • Spark ML StringIndexer 不同标签训练/测试

    我正在使用 Scala 并使用 StringIndexer 为训练集中的每个类别分配索引 它根据每个类别的频率分配索引 问题是 在我的测试数据中 类别的频率不同 因此 StringIndexer 为类别分配不同的索引 这使我无法正确评估模型
  • 自定义 UISegmentedControl,添加背景图像和选定的段色调颜色

    重复的this 但它不适合我 我已经使用 UICatalog 创建了 UISegmentedControl 并尝试更改所选段的颜色 我用过this改变颜色 背景图像工作正常 但它不会改变所选段的颜色 我应该做哪些修改 或者还有其他相同的方法
  • Android 每 1 分钟发出一次警报管理器?

    我想提供一项服务 火警管理器每隔 1 分钟间隔一次 但是 我的闹钟运行一次 仅限第一次 我跟随拉利特答案 private class Receiver extends BroadcastReceiver Override public vo
  • Pandas groupby:根据pandas groupby组中另一列中的数据选择一行后如何选择相邻列数据?

    我有一个数据库 部分如下所示 对于每个日期 都有持续时间条目 每个日期 1 20 并为每个持续时间列出项目 100 秒 每个项目在相邻列中都有多个关联的数据点 包括标识符 对于每个日期 我想选择最长的持续时间 然后 我想找到值最接近给定输入
  • C# Windows 服务创建进程但不执行它

    所以我检查了很多网站 研究了好几天 我还没有找到或提出自己的解决方案来解决这个问题 我知道 显然从 Windows Vista 开始 Windows 服务自在会话 0 中创建以来 无法与 GUI 可执行文件 例如控制台应用程序和属于非会话
  • 暂时从 Google Translate API 的字符串中删除 HTML 以降低成本

    我必须使用我们付费的 Google API 翻译一些详细信息 详细信息包含 HTML Google 对每个字符收费 我不想发送完整的内容 而只想发送英文文本 并删除 HTML 我可以使用 PHP 函数删除 HTML 标签和实体 但我必须在翻
  • ASP.NET MVC2 项目的 DDD 架构

    我正在尝试将域驱动开发 DDD 用于我的新 ASP NET MVC2 项目和 Entity Framework 4 经过一些研究 我在自己的类项目中对每个层提出了以下层约定 我的公司 域 public class User Contains
  • 如果使用java满足某些条件,如何为某一行设置颜色?

    我有一个jtable 表格摘要 其中一栏是 EXPIRY 我想突出显示客户的行 其到期日已在当前日期失效 我已经有了逻辑 但我无法使该行变成红色或任何其他颜色 这是我的代码 int count tableSummary getRowCoun
  • “\n”分隔符问题

    我有一个 stringbuilder 对象 其中添加了一行数据 添加每一行后 我在末尾附加一个 n 以指示新行 这个 stringbuilder 对象最终确定后被写入一个平面文件 当我在记事本中打开平面文件时 每行后面都会出现一个小矩形 并
  • Twitter API 更新限制错误 403

    我正在尝试使用 twitter4j api 从 twitter api 检索数据 一段时间后检索数据我收到以下错误 Exception in thread main 403 The request is understood but it
  • JQgrid动态添加Dropdown

    我想在 JQGrid 中动态添加下拉菜单 例如 我有以下类型的网格 现在 当我单击按钮时 应在网格中添加一个新行 对于新行 第一列数据将是下拉列表 第二个超链接 第三个下拉列表和第四个复选框 即它应该与第一行相同 对于每个按钮 单击新行时应
  • 什么可能导致 System.TypeLoadException?

    我正在使用 C 使用 VS2008 开发 Honeywell Dolphin 6100 的应用程序 Honeywell Dolphin 6100 是一款带有条形码扫描仪的移动计算机 使用类似 Windows CE 5 0 的操作系统 我想添
  • 无法通过 Azure Powershell 在新应用程序注册模块中设置“preAuthorizedApplications”对象

    简短的场景 多租户前端 javascript React JS Web 应用程序从浏览器调用多租户 ASP NET Core 2 2 WebAPI 验证 当用户登录时 基于用户的原始 Azure Active Directory 前端应用程
  • self = [超级初始化] 重新审视

    我偶然发现了这个帖子在 Objective C 中 为什么我应该检查 self super init 是否不为零 我能够了解这个语法 id initWithString NSString aString self super init if
  • 带有controlsfx通知组件的javafx NullPointerException

    我想开发一个使用controlsfx通知在系统托盘模式下显示一些通知的应用程序 在正常模式下 我的应用程序运行良好 并且可以成功显示通知 但是当我在系统托盘中隐藏阶段时 会发生 NullPointerException 我不知道如何解决这个
  • 将多个 pandas 数据帧导出到 csv 文件的最有效方法是什么?

    我有多个 pandas 数据框 df1 df2 df3 我想将它们全部导出到 csv 文件 df1 to csv df1 csv index False df2 to csv df2 csv index False df3 to csv d
  • 以两个不同的名称将 docker 容器添加到网络

    我正在尝试新的 docker 网络功能 我使用容器链接将旧设置迁移到新的桥接网络 到目前为止 我已经在同一主机上的多个容器之间启动并运行了专用桥接网络 现在我正在寻找一种方法来复制同一容器的多个链接别名 假设我有一个名为myBox加入 do
  • 只需从 PHP 中的字符串获取图像 URL [重复]

    这个问题在这里已经有答案了 从这样的字符串 img src images mylondon jpg 我正在尝试检索仅在 PHP 中其他地方使用的 url 我知道正则表达式是可行的方法 但我现在无法理解它们 有人可以帮忙吗 preg matc
  • DBGrid 停止当前行移动

    使用 d5 TDBGrid SQLite3 和 ZEOS 数据库有 2000 个项目 一列是 Active 布尔值 第二列是 ItemName 文本 IndexFiledNames 是 ItemName OnDblclick 切换 活动 开