设置TDBGrid可见行

5

我希望根据VisibleRows参数调整TDBGrid的高度,这个网格可能有标题也可能没有。

假设我从数据库中选择了100条记录,但是我希望网格的高度调整为仅显示前10行(使它们可见),数据集仍将保持100条记录。

例如:

procedure SetVisibleRows(DBGrid: TCustomDBGrid; VisibleRows: Integer);
begin
  ...
  DBGrid.Height := ???
end;

我知道如何获取可见的行:

type
  TCustomGridHack = class(TCustomGrid);

function GetVisibleRows(DBGrid: TCustomDBGrid): Integer;
begin
   Result := TCustomGridHack(DBGrid).VisibleRowCount;
end;

但是,有没有一种方法可以设置VisibleRowCount呢?


@nil,谢谢。我知道这是只读属性。我实际上从“增加或减少高度,直到VisibleRowCount和DesiredVisibleRows相同”开始——但我不喜欢它。请看我的答案,可能有一个解决方案。 - zig
我明白了,尝试那样做感觉不好。当时我尝试的是类似于你的方法,但基于网格创建的绘制信息。 - nil
@nil,我确实看到了GetVisibleRowCount方法,但是网格客户端高度可以通过TGridDrawInfo进行设置吗?我只发现了对它的计算。如果你有可用的代码,请随意分享 :) - zig
除了使滚动条行为古怪之外,不要做更多的事情。我在考虑像这样的东西: - nil
1
过程SetVisibleRows(DBGrid: TCustomDBGrid; VisibleRows: Integer); var AGridDrawInfo: TGridDrawInfo; AClientHeight: Integer; I: Integer; begin TDBGridAccess(DBGrid).CalcDrawInfo(AGridDrawInfo); AClientHeight := AGridDrawInfo.Vert.FixedBoundary; for I := AGridDrawInfo.Vert.FirstGridCell to VisibleRows do Inc(AClientHeight, (AGridDrawInfo.Vert.GetExtent(I) + AGridDrawInfo.Vert.EffectiveLineWidth)); DBGrid.ClientHeight := AClientHeight; end; - nil
@nil,谢谢。我稍微调整了一下你的代码。现在可以正常运行了! - zig
1个回答

2

这似乎起作用了(也许可以进一步优化):

type
  TCustomDBGridHack = class(TCustomDBGrid);

procedure SetVisibleRows(DBGrid: TCustomDBGrid; VisibleRows: Integer);
var
  TitleHeight, RowHeight: Integer;
begin
  with TCustomDBGridHack(DBGrid) do
  begin
    if dgTitles in Options then
    begin
      TitleHeight := RowHeights[0] + GridLineWidth;
      RowHeight := RowHeights[1] + GridLineWidth;
    end
    else
    begin
      TitleHeight := 0;
      RowHeight := RowHeights[0] + GridLineWidth;
    end;
  end;
  DBGrid.ClientHeight := TitleHeight + (RowHeight * VisibleRows) + 1;
end;

或者按照 @nil 建议的方式,使用 TGridDrawInfo。它可以产生更准确的结果(我稍作修改):

procedure SetVisibleRows(DBGrid: TCustomDBGrid; VisibleRows: Integer);
var
  DrawInfo: TGridDrawInfo;
  TitleHeight, RowHeight: Integer;
begin
  with TCustomDBGridHack(DBGrid) do
  begin
    CalcDrawInfo(DrawInfo);
    TitleHeight := DrawInfo.Vert.FixedBoundary;
    RowHeight := RowHeights[DrawInfo.Vert.FirstGridCell] + DrawInfo.Vert.EffectiveLineWidth;
  end;
  DBGrid.ClientHeight := TitleHeight + (RowHeight * VisibleRows) + 1;
end;

正如@nil所提到的,RowHeight也可以通过以下方式进行计算:
RowHeight := DrawInfo.Vert.GetExtent(DrawInfo.Vert.FirstGridCell) + DrawInfo.Vert.EffectiveLineWidth; 

我没有注意到任何不同之处(应进一步调查)。
上述内容可以进一步改进,使TDBGrid滚动条更好地调整:
procedure SetVisibleRows(DBGrid: TCustomDBGrid; VisibleRows: Integer);
var
  DrawInfo: TGridDrawInfo;
  TitleHeight, RowHeight: Integer;
  HasActiveDataSet: Boolean;
begin
  if VisibleRows < 0 then VisibleRows := 0;
  HasActiveDataSet := Assigned(DBGrid.DataSource) and
    Assigned(DBGrid.DataSource.DataSet) and
    DBGrid.DataSource.DataSet.Active;
  if HasActiveDataSet then
    DBGrid.DataSource.DataSet.DisableControls;
  try
    with TCustomDBGridHack(DBGrid) do
    begin
      CalcDrawInfo(DrawInfo);
      TitleHeight :=  DrawInfo.Vert.FixedBoundary;
      RowHeight := RowHeights[DrawInfo.Vert.FirstGridCell] + DrawInfo.Vert.EffectiveLineWidth;      
    end;
    DBGrid.ClientHeight := TitleHeight + (RowHeight * VisibleRows) + 1;
  finally
    if HasActiveDataSet then
      DBGrid.DataSource.DataSet.EnableControls;
  end;
end;

1
我建议进行小的编辑,使用DrawInfo而不是RowHeights。我不能说哪种方法更好。可能有情况需要考虑行高度的不同 - 据我所知,这是可能的。这就是为什么我认为循环行可能是必要的原因。我正在使用TSpinEdit动态更改VisibleRows,并注意到垂直滚动条更新是“懒惰”的。只有在更改高度后选择一行后才会更新。 - nil
@nil,谢谢。我已经进行了编辑并提到了另一个选项。但我没有注意到任何区别。据我所知,TDBgrid无法具有可变行高。因此,我认为可以放心地依赖于第一行数据。我现在才注意到垂直滚动条的奇怪行为。通过使用网格DataSource.DatSet.DisableControls/EnableControls(如果它附加了一个DataSet),可以“修复”它。 - zig
谢谢您编辑了那个,我的编辑被拒绝了。对于滚动条的不错的“修复”,我也无法理解。 - nil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接