我有一些TEdits链接到AdoQuery,而另一个TEdits链接到StringGrid。因此,当我更改网格中的选择时,“编辑”也会更改其内容,并从选定的单元格中获取数据。这是自动的,没有任何代码行。但是,当我使用AdoQuery.Filtered属性过滤AdoQuery时,此自动操作不起作用,并且Edits仅获得第一个单元格值。如何过滤AdoQuery并保持此StringGrid-Edits链接正常工作?

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

delphi - AdoQuery筛选器禁用StringGrid编辑功能-LMLPHP

最佳答案

请看下面的示例代码,它是一个独立的示例
ClientDataSet通过LiveBindings连接到某些TEdit和TStringGrid,其中
一种对命名TField中的值强加过滤器的工具。我也包括了
DFM的相关部分,以便您可以看到实时绑定。

该项目包括连接到DataSource1的标准TDBGrid,以比较其
TStringGrid的行为。

抛开过滤问题,仅编译并运行项目。使用Delphi
西雅图,我在StringGrid中看到的是ID = 5的行,而没有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属性设置为“ ID; Name”,则不会发生上述问题。

但是,尽管有上述怪癖,仍使用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

10-05 22:25