在DBGrid中移动列似乎移动附加的DataSet字段

时间:2009-12-31 00:19:47

标签: delphi tclientdataset tdbgrid tdataset

3 个答案:

答案 0 :(得分:3)

显然行为是设计的。实际上它与dbgrid无关。它仅仅是设置字段索引的列的副作用。例如,这句话,

ClientDataSet1.Fields [0] .Index:= 1;

将导致“Show ClientDataSet Structure”按钮的输出相应地更改,无论是否有网格。 TField.Index的文档声明;

“通过更改索引值来更改数据集中字段位置的顺序。更改索引值会影响数据网格中字段的显示顺序,但不会影响物理数据库表中字段的位置。”

应该得出结论反过来也应该是真的,改变网格中字段的顺序应该会导致字段索引被改变。


导致此问题的代码在TColumn.SetIndex中。 TCustomDBGrid.ColumnMoved为移动的列设置新索引,TColumn.SetIndex为该列的字段设置新索引。

procedure TColumn.SetIndex(Value: Integer);
[...]
        if (Col <> nil) then
        begin
          Fld := Col.Field;
          if Assigned(Fld) then
            Field.Index := Fld.Index;
        end;
[...]

答案 1 :(得分:1)

我认为我找到了解决这个问题的方法。我们需要使用Recordset COM对象的内部Fields属性,而不是使用VCL包装器字段。

以下是它应该如何引用:

qry.Recordset.Fields.Item[0].Value

这些字段不受您之前描述的行为的影响。所以我们仍然可以通过索引来引用这些字段。

测试一下,然后告诉我结果是什么。它对我有用。

编辑:

当然它只适用于ADO组件,而不适用于TClientDataSet ......

Edit2:

Cary我不知道这是否是你的问题的答案,但是我一直在推动embarcadero论坛上的人们和Wayne Niddery给了我关于所有这些Fields运动的非常详细的答案。

简而言之:如果你明确地在TDBGrid中定义列,那么字段索引就不会移动了!现在有点意义了,不是吗?

在这里阅读完整主题: https://forums.embarcadero.com/post!reply.jspa?messageID=197287

答案 2 :(得分:1)

Wodzu发布了针对ADO DataSet特定的重新排序的Field问题的解决方案,但他引导我找到了一个类似的解决方案,可用于所有DataSet(无论是否在 all 中正确实现) DataSet是另一个问题)。请注意,这个答案和Wodzu都不是原始问题的答案。相反,它是解决问题的解决方案,而问题与此工件的起源有关。

Wodzu解决方案引导我的解决方案是FieldByNumber,它是Fields属性的一种方法。使用FieldByNumber有两个有趣的方面。首先,您必须使用DataSet的Fields属性限定其引用。其次,与Fields数组(采用从零开始的索引器)不同,FieldByNumber是一种方法,它采用一个基于参数的参数来指示您想要引用的TField的位置。

以下是我在原始问题中发布的Button1事件处理程序的更新版本。此版本使用FieldByNumber。

procedure TForm1.Button1Click(Sender: TObject);
var
  sl: TStringList;
  i: Integer;
begin
  sl := TStringList.Create;
  try
    sl.Add('The Structure of ' + ClientDataSet1.Name +
      ' using FieldByNumber');
    sl.Add('- - - - - - - - - - - - - - - - - ');
    for i := 0 to ClientDataSet1.FieldCount - 1 do
      sl.Add(ClientDataSet1.Fields.FieldByNumber(i + 1).FieldName);
    ShowMessage(sl.Text);
  finally
    sl.Free;
  end;
end;

对于示例项目,此代码生成以下输出,而不管关联的DBGrid中的列的方向如何:

The Structure of ClientDataSet1 using FieldByNumber
- - - - - - - - - - - - - - - - - 
StartOfWeek
Label
Count
Active

要重复,请注意对底层TField的引用要求FieldByNumber通过对Fields的引用进行限定。此外,此方法的参数必须位于1到DataSet.FieldCount范围内。因此,要引用DataSet中的第一个字段,请使用以下代码:

ClientDataSet1.Fields.FieldByNumber(1)

与Fields数组一样,FieldByNumber返回TField引用。因此,如果要引用特定于特定TField类的方法,则必须将返回的值强制转换为适当的类。例如,要将TBlobField的内容保存到文件,您可能需要执行以下代码:

TBlobField(MyDataSet.Fields.FieldByNumber(6)).SaveToFile('c:\mypic.jpg');

请注意,我并不是建议您使用整数文字引用DataSet中的TField。就个人而言,通过一次性调用FieldByName来初始化的TField变量的使用更具可读性,并且不受表格结构物理顺序变化的影响(尽管不会对字段名称的变化产生影响!)。

但是,如果您有与DBGrids相关联的DataSet,其Columns可以重新排序,并且您使用整数文字作为Fields数组的索引器引用这些DataSet的字段,您可能需要考虑转换代码以使用DataSet.Fields .FieldByName方法。