📄 cb199910hh_f.asp.htm
字号:
column. If the field isn't a</SPAN></I></P>
<P class=Code><I><SPAN class=CodeBlue> // calculated field,
then set the IndexName of the</SPAN></I></P>
<P class=Code><I><SPAN class=CodeBlue> // ClientDataSet</SPAN>
to the FieldName of the field. If the</I></P>
<P class=Code><I><SPAN class=CodeBlue> // field is a calculated
field, then use the default index. </SPAN></I></P>
<P class=Code> <B> if</B> (Column->Field->FieldKind !=
fkCalculated) </P>
<P class=Code> ClientDataSet1->IndexName =
Column->Field->FieldName; </P>
<P class=Code> <B> else</B></P>
<P class=Code> ClientDataSet1->IndexName =
"DEFAULT_ORDER"; </P>
<P class=Code>}</P>
<P class=Captions><B>Figure 8: </B>Setting the index based on the column
that users clicked. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I
style="mso-bidi-font-style: normal">OnTitleClick</I> event handler passes
a pointer to a <I>TColumn</I> object. <I>TColumn</I> publishes a property
named <I>Field</I> that returns the <I>TField</I> for the selected column.
By looking at the <I>FieldName</I> property, we can determine the name of
the index. This is why the <I
style="mso-bidi-font-style: normal">CreateIndices</I> function set the
index names to be the same as the field names. We need a logical way to
determine the index name given to a <I>TField</I> object. The simplest way
to make this connection is to ensure that the index names and the field
names are the same. </P>
<P class=BodyText> </P>
<P class=BodyText>The <I
style="mso-bidi-font-style: normal">CreateIndices</I> function doesn't
attempt to create indexes for calculated fields. The <I>OnTitleClick</I>
event needs to detect when users click the column of a calculated field.
If users attempt to sort on a calculated field, the code assigns
"DEFAULT_ORDER" to the <I>IndexName</I> property. DEFAULT_ORDER is a
special index that is always available to ClientDataSet. Setting
<I>IndexName</I> to DEFAULT_ORDER sorts the dataset in its original order.
This order matches the order from the source dataset, which is the Query
component in this example. </P>
<P class=BodyText> </P>
<P class=Subheads>Conclusion</P>
<P class=BodyText>The ClientDataSet component is the workhorse of this
article. Without it, client-side sorting of data would be far more
arduous. The ClientDataSet method for sorting is faster and easier than
trying to accomplish the same task using a Query component. </P>
<P class=BodyText> </P>
<P class=BodyText>The grid example only sorts data in ascending order.
Many programs sort data in descending order when users click the same
column twice. How would we add that support to example two? One method
would be to create two indexes for each field. One index would sort in
ascending order, and the other would sort in descending order. The code
for this article includes a project that demonstrates how you could do
this (it's available for download). </P>
<P class=BodyText> </P>
<P class=BodyText>You may have noticed that the sorting examples
conveniently side step the issue of updating data in the database. If you
run the examples and modify the data in the grid, you might be surprised
to find that your changes will be gone the next time you run the program.
Recall that ClientDataSets are disconnected from their source datasets.
Changes made to the ClientDataSet aren't visible to the source dataset,
nor are they visible to the underlying database table. So how do we save
our changes to the database? By calling the <I>ApplyUpdates</I> method of
ClientDataSet. <I>ApplyUpdates</I> posts your changes to the database by
way of the Provider component. We'll discuss this update mechanism in
future articles that discuss how you can use ClientDataSet as a
replacement for the <I>RequestLive</I> property and cached updates. </P>
<P class=BodyText> </P>
<P class=BodyText><I>The code referenced in this article is available for
<SPAN class=CodeBlue><a href="download/cb199910hh_f.zip">download</a></SPAN>.</I></P>
<P class=BodyText> </P>
<P class=Biotext>Harold Howe works as an independent consultant in Des
Moines, IA. Harold graduated from Iowa State University in 1994 with a
degree in Electrical Engineering. He maintains the BCBDEV.COM Web site and
is a member of TeamB for C++Builder. Harold co-authored the book
<I>C++Builder How-To </I>[Waite Group Press, 1997] and he also contributed
to <I>C++Builder 4 Unleashed</I> [SAMS, 1999]. </P>
<P class=Subheads> </P>
<P class=Subheads><A name=ListingOne></A>Begin Listing One - Example 1:
main.h, header file for main form unit</P>
<P class=Code><SPAN class=CodeGrn>#ifndef mainH</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#define mainH</SPAN></P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><SPAN class=CodeGrn>#include <BdeProv.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Buttons.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Classes.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Controls.hpp>
</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Db.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <DBClient.hpp>
</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <DBGrids.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <DBTables.hpp>
</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <ExtCtrls.hpp>
</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Grids.hpp> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <Provider.hpp>
</SPAN></P>
<P class=Code><SPAN class=CodeGrn>#include <StdCtrls.hpp>
</SPAN></P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>class</B> TForm1 : <B>public</B> TForm</P>
<P class=Code>{</P>
<P class=Code><B> __published</B>:</P>
<P class=Code> TQuery *Query1; </P>
<P class=Code> TProvider *Provider1; </P>
<P class=Code> TClientDataSet *ClientDataSet1; </P>
<P class=Code> TPanel *Panel1; </P>
<P class=Code> TSpeedButton *btnOpen; </P>
<P class=Code> TSpeedButton *btnClose; </P>
<P class=Code> TDBGrid *DBGrid1; </P>
<P class=Code> TDataSource *DataSource1; </P>
<P class=Code> TRadioButton *btnItemsTotal; </P>
<P class=Code> TLabel *Label1; </P>
<P class=Code> TRadioButton *btnPaymentMethod; </P>
<P class=Code> <B> void</B> <B>__fastcall</B>
btnOpenClick(TObject *Sender); </P>
<P class=Code> <B> void</B> <B>__fastcall</B>
btnCloseClick(TObject *Sender); </P>
<P class=Code> <B> void</B> <B>__fastcall</B>
SortingChanged(TObject *Sender); </P>
<P class=Code><B> private</B>:</P>
<P class=Code> <B> void</B> CreateIndices();</P>
<P class=Code> <B> void</B> SelectIndex();</P>
<P class=Code><B> public</B>:</P>
<P class=Code> <B> __fastcall</B>
TForm1(TComponent* Owner); </P>
<P class=Code>};</P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>extern</B> PACKAGE TForm1 *Form1; </P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><SPAN class=CodeGrn>#endif</SPAN></P>
<P class=Subheads>End Listing One</P>
<P class=BodyText> </P>
<P class=Subheads><A name=ListingTwo></A>Begin Listing Two - Example 1:
main.cpp, source file for main form unit</P>
<P class=Code><I><SPAN class=CodeBlue>// </SPAN></I><SPAN
class=CodeGrn>#include <vcl.h> </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#pragma hdrstop</SPAN></P>
<P class=Code> </P>
<P class=Code><SPAN class=CodeGrn>#include "main.h" </SPAN></P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><SPAN class=CodeGrn>#pragma package(smart_init) </SPAN></P>
<P class=Code><SPAN class=CodeGrn>#pragma resource "*.dfm" </SPAN></P>
<P class=Code>TForm1 *Form1; </P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>__fastcall</B> TForm1::TForm1(TComponent* Owner) </P>
<P class=Code> : TForm(Owner) </P>
<P class=Code>{</P>
<P class=Code> CreateIndices();</P>
<P class=Code> SelectIndex();</P>
<P class=Code>}</P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>void</B> TForm1::CreateIndices()</P>
<P class=Code>{</P>
<P class=Code> //<I> <SPAN class=CodeBlue>Creating the index in
Figure 1. </SPAN></I></P>
<P class=Code> TIndexDef *ItemsIndex =</P>
<P
class=Code> ClientDataSet1->IndexDefs->AddIndexDef();</P>
<P class=Code> ItemsIndex->Name =
"ItemsTotal"; </P>
<P class=Code> ItemsIndex->Fields = "ItemsTotal"; </P>
<P class=Code> </P>
<P class=Code> TIndexDef *PaymentMethodIndex =</P>
<P
class=Code> ClientDataSet1->IndexDefs->AddIndexDef();</P>
<P class=Code> PaymentMethodIndex->Name =
"PaymentMethod"; </P>
<P class=Code> PaymentMethodIndex->Fields = "PaymentMethod";
</P>
<P class=Code>}</P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>void</B> TForm1::SelectIndex()</P>
<P class=Code>{</P>
<P class=Code> <B> if</B> (btnItemsTotal->Checked) </P>
<P class=Code> ClientDataSet1->IndexName =
"ItemsTotal"; </P>
<P class=Code> <B> else</B></P>
<P class=Code> ClientDataSet1->IndexName =
"PaymentMethod"; </P>
<P class=Code>}</P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code><B>void</B> <B
style="mso-bidi-font-weight: normal">__fastcall</B>
TForm1::btnOpenClick(TObject *Sender) </P>
<P class=Code>{</P>
<P class=Code> ClientDataSet1->Active = <B
style="mso-bidi-font-weight: normal">true</B>;</P>
<P class=Code>}</P>
<P class=Code><I><SPAN class=CodeBlue>//
------------------------------------------------------------</SPAN></I></P>
<P class=Code> </P>
<P class=Code><B>void</B> <B
style="mso-bidi-font-weight: normal">__fastcall</B>
TForm1::btnCloseClick(TObject *Sender) </P>
<P class=Code>{</P>
<P class=Code> ClientDataSet1->Active = <B
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -