在我们的主数据输入屏幕上,我们在OnBeforePost事件中有一个OK/Cancel对话框.
Dataset.Cancel;
这意味着什么,回滚任何更改并将数据集置于浏览模式.
这对大多数客户来说都很好,但我们被问到是否可以更改为
如果他们想要取消,他们可以使用取消按钮.
查看源代码procedure TDataSet.Post;
看起来不可能以这种方式使用事件.
任何人都有任何想法可以这样做吗?
跟进:这就是我现在选择处理它的方式
case MessageDlg('Save Changes?', mtWarning, [mbYes, mbNo, mbAbort], 0) of
mrYes: ;
mrNo: Dataset.Cancel;
mrAbort: Abort;
mrNone: Abort;
end;
Run Code Online (Sandbox Code Playgroud) 我一直在查看TDataset类及其字符串字段,在Delphi XE2中注意到AsWideString返回一种类型的UnicodeString.但是它从函数TField.AsString:String中获取值,而后者又调用TFIeld.AsAnsiString:AnsiString.因此任何unicode字符都会丢失?传递给TDataset.GetFieldData的缓冲区也被声明为AnsiChar数组.
我理解正确吗?
我上周观察到了一些我没想到的事情,并将在下面描述.我很好奇为什么会这样.它是TDataSet类内部的东西,TDBGrid的工件还是别的东西?
打开的ClientDataSet中的字段顺序已更改.具体来说,我在使用FieldDefs定义其结构后通过调用CreateDatatSet在代码中创建了一个ClientDataSet.此ClientDataSet结构中的第一个字段是名为StartOfWeek的Date字段.不久之后,我编写的代码(假设StartOfWeek字段位于零位置,ClientDataSet.Fields [0])失败,因为StartOfWeek字段不再是ClientDataSet中的第一个字段.
经过一番调查后,我了解到ClientDataSet中的每个字段都可能在给定时刻出现在创建ClientDataSet时与原始结构不同的某个位置.我不知道这可能会发生,并且对谷歌的搜索也没有提到这种效果.
发生了什么不是魔术.这些字段本身并没有改变位置,也没有根据我在代码中所做的任何事情而改变.导致字段在物理上看起来改变ClientDataSet中位置的原因是用户已经更改了ClientDataSet附加到的DbGrid中的列的顺序(当然是通过DataSource组件).我在Delphi 7,Delphi 2007和Delphi 2010中复制了这个效果.
我创建了一个非常简单的Delphi应用程序来演示这种效果.它由一个包含一个DBGrid,一个DataSource,两个ClientDataSets和两个Buttons的表单组成.此表单的OnCreate事件处理程序如下所示
procedure TForm1.FormCreate(Sender: TObject);
begin
with ClientDataSet1.FieldDefs do
begin
Clear;
Add('StartOfWeek', ftDate);
Add('Label', ftString, 30);
Add('Count', ftInteger);
Add('Active', ftBoolean);
end;
ClientDataSet1.CreateDataSet;
end;
Run Code Online (Sandbox Code Playgroud)
Button1,标记为Show ClientDataSet Structure,包含以下OnClick事件处理程序.
procedure TForm1.Button1Click(Sender: TObject);
var
sl: TStringList;
i: Integer;
begin
sl := TStringList.Create;
try
sl.Add('The Structure of ' + ClientDataSet1.Name);
sl.Add('- - - - - - - - - - - - - - - - - ');
for i := 0 to ClientDataSet1.FieldCount - 1 do
sl.Add(ClientDataSet1.Fields[i].FieldName); …
Run Code Online (Sandbox Code Playgroud) 有谁知道一个TDataSet的后裔,与泛型和RTTI的作品,让我可以写这样的代码,并利用数据感知组件的GUI的?:
...
ds:TDataset<TPerson>;
...
procedure DoStuff;
begin
ds:=TDataset<TPerson>.create;
ds.add(TPerson.Create('A.','Hitler',77));
ds.add(TPerson.Create('O.','Bin Laden',88));
end;
Run Code Online (Sandbox Code Playgroud)
这应该是可能的.fielddef可以通过RTTI创建,因为已知数据的确切类型.值也可以来回自动编组,因此您可以查看和编辑类或记录中的数据.
我讨厌必须编写大量无用的编组代码,而已经通过RTTI获得所需的信息.
或者有人曾经写过某种TEnumerable < - > TDataset适配器?
这样的事情是存在的,还是我应该开始写一个?
...
我能找到的最接近的东西是来自Mastering Delphi 7的Marco Cantu的一个(优秀的!)示例,但是代码本身并没有使用泛型,新RTTI系统或属性等新语言功能,而且它没有使用Unicode delphi.自D7以来,TDataset也发生了变化.
在经典的Delphi数据库应用程序中,我们有一个表单,一组通过TDataSources连接到TDataSets的数据感知可视控件.如果想要使用MVC模型设计数据库应用程序,在哪里放置TDataSet组件?他们应该保持形式,因此成为View的一部分吗?或者它们应该封装在一些Model对象中?如果后者如何绑定到可视组件?
我想创建一个"重复记录"操作,在调用时,它会复制任何TDataSet
后代中的当前记录.如何确定数据集是否为主/明细关系的主数据集?随着TClientDataSet
这是相当容易的,但我需要用的所有后代使用这个动作TDataSet
.
当底层数据集中的记录数大于时,是否可以从DBGrid的最顶行中获取从基础数据集显示的行号,而不是最顶行是当前选定的行. DBGrid中显示的行数,并且已滚动DBGrid.
这是我的问题.从附加到DBGrid的拖放事件处理程序,我可以使用MyGrid.MouseCoord(X,Y).Y确定drop事件与DBGrid的哪个可见行相关联.当基础数据集包含的记录数小于或等于DBGrid中显示的行数时,此值也是基础数据集中关联记录的行号.
当基础数据集包含的记录多于DBGrid中可见行数时,MyGrid.MouseCoord(X,Y).Y和TDataSet(MyGrid.DataSource.DataSet).RecNo仅在数据集的第一行出现时相同在网格的第一行.
有没有办法在没有选择DBGrid行的情况下识别DBGrid中最顶层显示记录的基础数据集(或偏移量)中的记录号?我知道如果我实际上选择了DBGrid的最顶行,那么我可以使用TDataSet(MyGrid.DataSource.DataSet).RecNo来获取底层数据集的当前记录号.但是,从DBGrid.OnDragOver或DBGrid.OnDragDrop事件我只有DBGrid和鼠标坐标的引用(我可以从中确定网格的哪一行是放置的目标).
例如,如果我可以确定DBGrid在网格的最顶行中的基础数据集中显示第三条记录,我的问题就解决了.同样,如果我可以读取特定行的底层TField(例如,最顶行)而没有选择该行,我就拥有了我需要的东西.但是,我看不到这样做的方法.
任何建议将不胜感激.
编辑:我之前发布了一篇关于拖放到DBGrid的博客.有了这个新信息,我可以解决以前已知的问题.我将在本周的某个时候更新该博客,并且一旦我这样做,就会在这里添加一个指向该博客的链接.
还有一个问题.当可见行的数量小于基础记录的数量时,我们还需要计算在最后一个可见行之后发生的下降.在最后一个可见行之后删除时,MouseCoord(x,y).Y返回-1.
以下是对Uwe代码的修改,以实现这一目的:
function TDBGridHelper.RecNoFromVisibleRow(Value: Integer): Integer;
begin
if Value = -1 then
begin
Result := DataSource.DataSet.RecNo - Row + TopRow + VisibleRowCount
end
else
begin
Result := DataSource.DataSet.RecNo - Row + TopRow + Value;
if dgTitles in Options then
Dec(Result);
end;
end;
Run Code Online (Sandbox Code Playgroud)
编辑:正如我在原始问题中提到的,我对这个答案很感兴趣,以便修复我的代码中实现拖放到DBGRid中的行为.有了这个答案,我已经更新了我的拖放行为,我在博客中写过这个更新.您可以在以下URL找到此讨论,包括原始博客文章的链接:拖放到DBGrid中重新访问
我喜欢在用户点击它们时没有意义的情况下禁用控件.
一个特殊情况是一组自定义菜单按钮,用于模拟标准的第一个,前一个,下一个和最后一个按钮TDBNavigator
.
当用户单击第一个按钮时,第一个和前一个按钮都被禁用.
当用户然后单击下一个和前一个按钮时,底层TDataSet
位于与之前相同的记录上,但是仍然启用了第一个和前一个按钮.
当前的实现如下所示:
NavigationFirstButton.Enabled := not DataSet.IsEmpty and not DataSet.Bof;
NavigationPriorButton.Enabled := not DataSet.IsEmpty and not DataSet.Bof;
NavigationNextButton.Enabled := not DataSet.IsEmpty and not DataSet.Eof;
NavigationLastButton.Enabled := not DataSet.IsEmpty and not DataSet.Eof;
Run Code Online (Sandbox Code Playgroud)
Bof
并且Eof
不是禁用按钮的正确方法,因为我必须事先知道当前记录是否是第一个/最后一个记录.
所以我想用一个IsFirstRecord
和IsLastRecord
方法重写这个:
function IsFirstRecord(ADataSet: TDataSet): Boolean;
begin
Result := ADataSet.RecNo = 0;
end;
function IsLastRecord(ADataSet: TDataSet): Boolean;
begin
Result := ADataSet.RecNo = ADataSet.RecordCount - 1;
end;
Run Code Online (Sandbox Code Playgroud)
我不认为这是一个好主意,因为我已经看到第一个记录RecNo = 0
不正确的情况.(即过滤的TADSQuery)
什么是可靠的实现IsFirstRecord
和IsLastRecord
?甚至可以使用当前 …
我是Delphi开发人员和C#开发人员.C#具有DataTable类,支持对Rows的随机访问.是否存在类似DataTable(C#)的第三方TDataSet(Delphi)组件?
I am looking for a way to provide a ListSource to a TDBLookupComboBox in delphi without having an actual table on the database server to draw that list from. The DataField for the Combo Box is a 1 character field that contains a coded value such as 'A' = 'Drivers License', 'B' = 'Passport', 'C' = 'Library Card', etc. That is to say that the table only contains A, B, or C. The application is responsible for Displaying 'Drivers License' …
delphi ×10
tdataset ×10
delphi-xe2 ×2
c# ×1
data-aware ×1
data-binding ×1
database ×1
dbgrid ×1
delphi-7 ×1
delphi-xe ×1
generics ×1
rtti ×1
tdbgrid ×1
unicode ×1