Update: Ich glaube, ich weiß jetzt verstehen, was Sie fragen tatsächlich, was, dass selbst, wenn Sie die DataSetDelete Aktion der Datasource nicht zugewiesen lassen, wie es ist, dass die Aktion irgendwie schafft „wissen“, welche Datenquelle operieren?
Es gibt eine Erklärung dafür, ob alle Ihre Datenquellen TDBGrids verbunden sind oder einer anderen DB-Aware-Komponente, deren Datenlink enthält Code ähnlich der folgenden:
function TCustomDBGrid.UpdateAction(Action: TBasicAction): Boolean;
begin
Result := (DataLink <> nil) and DataLink.UpdateAction(Action);
end;
Wenn Sie einen Haltepunkt setzen auf die Result := ...
Sie werden feststellen, dass es wiederholt aufgerufen wird, während die App ausgeführt wird.
Jetzt versucht dies mit meinem Code unten:
trennen die beiden DBGrids von ihrer repective Datenquelle, dann kompilieren und ausführen:
Ergebnis: (!) Der DataSetDelete Menüpunkt ist deaktiviert.
Als nächstes verbinden Sie DBGrid2 mit DataSource2. Kompilieren und ausführen.
Ergebnis: Der Menüeintrag DataSetDelete ist aktiviert und klicken Sie auf es löscht die aktuelle Zeile von CDS2.
Als nächstes verbinden Sie DBGrid1 mit DataSource1. Kompilieren und ausführen.
Ergebnis: Der DataSetDelete Menüpunkt ist aktiviert und Anklicken löscht die aktuelle Zeile aus CDS1.
Wie Sie sehen können, es sei denn, Ihr Code explizit der Datasource Eigenschaft DataSetAction setzt diese Aktion arbeitet auf der Datenquelle des ersten Datenverbindungs die gibt Wahr zurück, von einem beliebigen DB-aware UpdateAction
Funktion der Komponente.
Mit anderen Worten, es ist nicht so sehr, dass die DataSetDelete Aktion „weiß“, welche Datenquelle zu verwenden, wenn Sie die DataSetDelete Aktion der Datasource-Eigenschaft nicht zugewiesen verlassen, sondern vielmehr, dass die DB-Aware Komponenten Datenverbindungen, die sagen die Aktion welche Datenquelle aktiv ist.
Update 2 Um zu sehen, was ich meine, entfernen Sie alle derzeit verfügbaren Handler für OnExecute des DataSetDelete. Dann setzen Sie einen Breakpoint auf TDataSetDelete.ExecuteTarget
in DBActns.Pas. Wenn der Fehler auftritt, sehen Sie sich den Aufruf-Stack an, und Sie werden feststellen, dass er von TCustomDBGrid.ExecuteAction aufgerufen wird, sodass die Identität des Datasets an die DataSetDelete-Aktion übergeben wird. Daher gibt es keine Möglichkeit, dies herauszufinden die Identität des Datasets von der DataSetDelete-Aktion selbst.
Es gibt jedoch einen einfachen Weg dazu. Bringen Sie die folgenden BeforeDelete-Handler für jede Ihrer Datensätze:
procedure TCDSForm.CDS1BeforeDelete(DataSet: TDataSet);
begin
if MessageDlg(DataSet.Name + ': Delete record?', mtConfirmation, [mbYes, mbNo], 0) <> mrYes then
Abort;
end;
Dann ob Sie versuchen, einen Datensatz Datensatz zu löschen, ob die DataSetDelete Aktion mit oder nicht, wird dieser Event-Handler aufgerufen werden, und wenn der Benutzer doesn‘ Wenn Sie mit "Ja" antworten, wird die Abbruchprozedur aufgerufen, wodurch eine stumme Ausnahme ausgelöst wird, die verhindert, dass der Löschvorgang fortgesetzt wird.
==============
Ursprüngliche Antwort folgt. Ich werde es später
aufzuräumen Wenn ich Sie richtig bin zu verstehen, das Beispielprojekt unten sollte das tun, was Sie wollen.
Meine Frage ist: Wie kann ich den aktiven Datenquelle-component lese
Die Antwort darauf ist, dass die TDataSetDelete Aktion eine Datasource-Eigenschaft hat und es ist nur eine Frage, die Datenquelle, auf die die Einstellung Sie wollen aktiv sein.
„Delphi weiß, welche Datenquelle ist aktiv“ Nein, natürlich ist es nicht, wie könnte es möglicherweise bis Sie es sagen, welche Datenquelle Sie die DataSetDelete Aktion wollen auf arbeiten? Und die Art, wie Sie das tun, ist seine Eigenschaft DataSource
zu setzen. Zu folgen, was ich meine, kompilieren Sie den Code unten, einen Haltepunkt auf
Caption := 'Execute'
innerhalb DataSetDelete1Execute
, dann kompilieren & das Projekt ausführen und klicken Sie auf den Menüpunkt DataSetDelete1Execute. Wenn der Haltepunkt ausgelöst wird, evaluieren Sie `TDataSetDelete (Sender) .DataSource. Sie werden der Wert Nil finden, weil Sie haben (noch) nicht die Aktion gesagt, die Datenquelle die Wirkung auf den Betrieb ist.
Dann Kommentar- der Linie
SetDataSource(DataSource1);
in FormCreate
und die Auswertung wiederholen. Jetzt weiß die Aktion , weil Sie es gesagt haben, welche Datenquelle es als aktiv betrachten sollte.
Falls Sie es verpasst erstes Mal, es ist die Linie
DatasetDelete1.DataSource := FDataSource;
in procedure TCDSForm.SetDataSource(const Value: TDataSource)
, die die Datenmenge, die die DatasetDelete1 Aktion verwendet setzt.
Btw, gibt es keine "Magie" zu einem dieser - Blick auf die Delphi-Quelle
function TDataSetAction.GetDataSet(Target: TObject): TDataSet;
begin
{ We could cast Target as a TDataSource since HandlesTarget "should" be
called before ExecuteTarget and UpdateTarget, however, we're being safe. }
Result := (Target as TDataSource).DataSet;
end;
und
procedure TDataSetDelete.ExecuteTarget(Target: TObject);
begin
GetDataSet(Target).Delete;
end;
-Code (aktualisiert):
unit cdsActionListu;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
Grids, DBGrids, DB, DBClient, StdCtrls, ExtCtrls, DBCtrls, ActnList,
DBActns, Menus;
type
TCDSForm = class(TForm)
CDS1: TClientDataSet;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
DBNavigator1: TDBNavigator;
DBGrid2: TDBGrid;
CDS2: TClientDataSet;
DataSource2: TDataSource;
DBNavigator2: TDBNavigator;
ActionList1: TActionList;
DataSetDelete1: TDataSetDelete;
MainMenu1: TMainMenu;
actSelectDataSource: TAction;
ListBox1: TListBox;
DataSetDelete11: TMenuItem;
procedure DataSetDelete1Execute(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
private
FDataSource: TDataSource;
procedure SetDataSource(const Value: TDataSource);
public
property ActiveDataSource : TDataSource read FDataSource write SetDataSource;
end;
var
CDSForm: TCDSForm;
implementation
{$R *.DFM}
function CreateField(AFieldClass : TFieldClass; AOwner : TComponent; ADataSet : TDataSet;
AFieldName, AName : String; ASize : Integer; AFieldKind : TFieldKind) : TField;
begin
Result := AFieldClass.Create(AOwner);
Result.FieldKind := AFieldKind;
Result.FieldName := AFieldName;
Result.Name := AName;
Result.Size := ASize;
Result.DataSet := ADataSet;
end;
procedure TCDSForm.DataSetDelete1Execute(Sender: TObject);
begin
Caption := 'Execute';
{ uncomment the following to actually delete the record
if MessageDlg('Delete record?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then begin
TDataSetDelete(Sender).DataSource.DataSet.Delete;
end;
}
end;
procedure TCDSForm.FormCreate(Sender: TObject);
var
Field : TField;
begin
Field := CreateField(TIntegerField, Self, CDS1, 'ID', 'CDS1ID', 0, fkData);
Field := CreateField(TStringField, Self, CDS1, 'StringField', 'CDS1Stringfield', 40, fkData);
CDS1.CreateDataSet;
CDS1.InsertRecord([1, 'CDS1 Value1']);
CDS1.InsertRecord([2, 'CDS1 Value2']);
Field := CreateField(TIntegerField, Self, CDS2, 'ID', 'CDS2ID', 0, fkData);
Field := CreateField(TStringField, Self, CDS2, 'StringField', 'CDS2Stringfield', 40, fkData);
CDS2.CreateDataSet;
CDS2.InsertRecord([1, 'CDS2 Value1']);
CDS2.InsertRecord([2, 'CDS2 Value2']);
Listbox1.Items.AddObject(Datasource1.Name, DataSource1);
Listbox1.Items.AddObject(Datasource2.Name, DataSource2);
// SetDataSource(DataSource1);
end;
procedure TCDSForm.ListBox1Click(Sender: TObject);
var
Index : Integer;
begin
Index := Listbox1.ItemIndex;
SetDataSource(TDataSource(Listbox1.Items.Objects[Index]));
end;
procedure TCDSForm.SetDataSource(const Value: TDataSource);
var
Index : Integer;
begin
FDataSource := Value;
DatasetDelete1.DataSource := FDataSource;
Index := ListBox1.Items.IndexOf(Value.Name);
if Index <> ListBox1.ItemIndex then
ListBox1.ItemIndex := Index;
Caption := 'Active DS ' + FDataSource.Name;
end;
Es tut mir leid, wir können Ihre s nicht sehen riechen oder lesen Sie Ihre Gedanken. Bitte geben Sie weitere Informationen darüber an, wie Ihre Anwendung funktioniert. Ab sofort kann ich nicht ausrechnen, was Ihre Bewerbung tut. –
Entschuldigung. aber für Delphi-Programmierer dachte ich, dass ein TDatasetdelete, das eine Standard-TAction ist, vertraut war. Das tut mir leid. – user3415259
@KenWhite: Eigentlich (und sehr zu meiner Überraschung) scheint das OP einen Punkt zu haben - bitte sehen Sie das Update zu meiner Antwort. – MartynA