AdoQuery过滤器禁用StringGrid编辑功能

时间:2016-02-23 16:34:22

标签: delphi

我有一些链接到AdoQuery的TEdits和一个链接到StringGrid的TEdits。因此,当我更改网格中的选择时,编辑也会更改其内容,并从所选单元格中获取数据。这是自动的,没有任何代码行。
但是当我使用#include <stdlib.h> #include <stdio.h> struct FooBar { int bar; } FooBar; struct FooBar *foo(void) { struct FooBar *test = malloc(sizeof(*test)); test->bar = 42; return test; } int main (void) { printf("%d\n", foo()->bar); return 1; } 属性过滤AdoQuery时,这个自动操作不起作用,并且Edits只获取第一个单元格值。
如何过滤AdoQuery并保持此StringGrid-Edits链接正常工作?

编辑:我已经添加了问题的图像,如您所见,即使选择了第二个记录,编辑仍保留第一个记录的值。忽略其他列,只有两个正在测试中。

Exemple

1 个答案:

答案 0 :(得分:2)

看看下面的示例代码,这是一个自包含的示例 ClientDataSet通过LiveBindings连接到一些TEdits和一个TStringGrid,用 在命名的TField中对值赋予过滤器的工具。我也包括在内 DFM的相关部分,以便您可以看到实时绑定。

该项目包括一个连接到DataSource1的标准TDBGrid,用于比较它 使用TStringGrid的行为。

不考虑过滤问题,只需编译并运行项目。使用Delphi 西雅图,我在StringGrid中看到的不是ID = 5的行,而是两行 ID = 6,这显然是错误的。 DBGrid正确显示行,包括 ID = 5。

使用DBNavigator,edID,edName和edValue在StringGrid中移动 即使StringGrid没有,TEDits也会显示正确的值。如果我 使用edName TEdit开始编辑ID = 6的第一行的Name列 StringGrid立即纠正自己以显示行ID = 5而不是第一个ID = 6。

因此,在这个简单的项目中,实时绑定似乎有问题,即使没有进行过滤也是如此。我发现如果ClientDataSet的IndexFieldNames属性设置为&#39; ID; Name&#39;。

,我所描述的问题就不会发生。

然而,尽管有上述怪癖,请使用edFilterFieldName和 edFilterValue TEdits似乎工作正常,似乎没有显示问题 你说你有。我已经使用了ClientDataSet,因此我可以生成 项目代码中的一些测试数据。但是,我无法立即明白为什么 以类似的方式过滤AdoQuery会有问题。

代码

TForm1 = class(TForm)
  StringGrid1: TStringGrid;
  DataSource1: TDataSource;
  edFilterFieldName: TEdit;
  edFilterValue: TEdit;
  Memo1: TMemo;
  CDS1: TClientDataSet;
  CDS1Name: TStringField;
  CDS1Value: TStringField;
  edName: TEdit;
  edValue: TEdit;
  BindingsList1: TBindingsList;
  CDS1ID: TIntegerField;
  DBGrid1: TDBGrid;
  edID: TEdit;
  LinkControlToField1: TLinkControlToField;
  BindSourceDB1: TBindSourceDB;
  LinkControlToField2: TLinkControlToField;
  LinkControlToField3: TLinkControlToField;
  LinkGridToDataSource1: TLinkGridToDataSource;
  DBNavigator1: TDBNavigator;
  procedure FormCreate(Sender: TObject);
  procedure edFilterFieldNameChange(Sender: TObject);
  procedure edFilterValueChange(Sender: TObject);
  procedure CDS1NewRecord(DataSet: TDataSet);
private
  FFilterFieldName : String;
  FFilterValue : String;
  procedure SetFilterFieldName(const Value: String);
  procedure SetFilterValue(const Value: String);
  procedure UpdateFilter;
public
  NextID : Integer;
  property FilterFieldName : String read FFilterFieldName write SetFilterFieldName;
  property FilterValue : String read FFilterValue write SetFilterValue;
end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i : Integer;
begin
  // AutoPost := True;
  CDS1.IndexFieldNames := 'ID';
  CDS1.CreateDataSet;

  for i := 1 to 6 do begin
    CDS1.Insert;
    CDS1.FieldByName('Name').AsString := 'Name  ' + IntToStr(i);;
    CDs1.FieldByName('Value').AsString := 'Value  ' + IntToStr(i);
    CDS1.Post;
  end;

  CDS1.First;
  StringGrid1.Invalidate;
  FilterFieldName := edFilterFieldName.Text;
  FilterValue := edFilterValue.Text;
end;

procedure TForm1.CDS1NewRecord(DataSet: TDataSet);
begin
  Inc(NextID);
  DataSet.FieldByName('ID').AsInteger := NextID;
end;

procedure TForm1.edFilterFieldNameChange(Sender: TObject);
begin
  FilterFieldName := edFilterFieldName.Text;
end;

procedure TForm1.edFilterValueChange(Sender: TObject);
begin
  FilterValue := edFilterValue.Text;
end;

procedure TForm1.SetFilterFieldName(const Value: String);
begin
  if FilterFieldName <> Value then begin
    FFilterFieldName := Value;
    UpdateFilter;
  end;
end;

procedure TForm1.UpdateFilter;
var
  Expr : String;
begin
  if CDS1.FieldByName(FilterFieldName) = Nil then begin
    CDS1.Filtered := False;
    exit;
  end;
  CDS1.DisableControls;
  if FilterValue <> '' then begin
    Expr := FilterFieldName + ' like ' + QuotedStr('%' + FilterValue + '%');
//    Expr := 'substring(FilterFieldName, 1, 1)' + ' = ' + QuotedStr(FilterValue);
    Memo1.Lines.Add(Expr);
    CDS1.Filter := Expr;
    CDS1.Filtered := True;
  end
  else
    CDS1.Filtered := False;
  CDS1.EnableControls;
end;

procedure TForm1.SetFilterValue(const Value: String);
begin
  if FilterValue <> Value then begin
    FFilterValue := Value;
    UpdateFilter;
  end;
end;

部分DFM

object DBNavigator1: TDBNavigator
  Left = 600
  Top = 208
  Width = 240
  Height = 25
  DataSource = DataSource1
  TabOrder = 8
end
object DataSource1: TDataSource
  DataSet = CDS1
  Left = 128
  Top = 24
end
object CDS1: TClientDataSet
  Aggregates = <>
  Params = <>
  OnNewRecord = CDS1NewRecord
  Left = 72
  Top = 24
  object CDS1ID: TIntegerField
    FieldName = 'ID'
  end
  object CDS1Name: TStringField
    FieldName = 'Name'
    Size = 40
  end
  object CDS1Value: TStringField
    FieldName = 'Value'
    Size = 80
  end
end
object BindingsList1: TBindingsList
  Methods = <>
  OutputConverters = <>
  Left = 128
  Top = 88
  object LinkControlToField1: TLinkControlToField
    Category = 'Quick Bindings'
    DataSource = BindSourceDB1
    FieldName = 'ID'
    Control = edID
    Track = False
  end
  object LinkControlToField2: TLinkControlToField
    Category = 'Quick Bindings'
    DataSource = BindSourceDB1
    FieldName = 'Name'
    Control = edName
    Track = False
  end
  object LinkControlToField3: TLinkControlToField
    Category = 'Quick Bindings'
    DataSource = BindSourceDB1
    FieldName = 'Value'
    Control = edValue
    Track = False
  end
  object LinkGridToDataSource1: TLinkGridToDataSource
    Category = 'Quick Bindings'
    DataSource = BindSourceDB1
    GridControl = StringGrid1
    Columns = <
      item
        MemberName = 'ID'
      end
      item
        MemberName = 'Name'
      end
      item
        MemberName = 'Value'
      end>
  end
end
object BindSourceDB1: TBindSourceDB
  DataSource = DataSource1
  ScopeMappings = <>
  Left = 216
  Top = 32
end