⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cb199910hh_f.asp.htm

📁 C++builder学习资料C++builder
💻 HTM
📖 第 1 页 / 共 5 页
字号:
      One</A> and <A   

      href="cb199910hh_f.asp.htm#ListingTwo">Listing   

      Two</A> show the code for this example, which is responsible for three   

      things. First, it must create the two indexes that we need to sort the   

      data. Second, it must give users a way to open and close the dataset when   

      users click the Open and Close buttons. Third, the code must select the   

      correct index when users click one of the radio buttons. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText>The creation of the indexes is handled by a member   

      function named <I style="mso-bidi-font-style: normal">CreateIndices</I>.   

      <I>CreateIndices</I> uses the <I>IndexDefs</I> property of ClientDataSet   

      to create two <I>TIndexDef</I> objects. The first object is the index for   

      the ItemsTotal field, and the second object is for the PaymentMethod   

      field: </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>void</B> TForm1::CreateIndices()</P>  

      <P class=Code>{</P>  

      <P class=Code>&nbsp;&nbsp;TIndexDef   

      *ItemsIndex=ClientDataSet1-&gt;IndexDefs-&gt;AddIndexDef();</P>  

      <P class=Code>&nbsp;&nbsp;ItemsIndex-&gt;Name&nbsp;&nbsp;&nbsp;=   

      "ItemsTotal"; </P>  

      <P class=Code>&nbsp;&nbsp;ItemsIndex-&gt;Fields = "ItemsTotal"; </P>  

      <P class=Code> </P>  

      <P class=Code>&nbsp;&nbsp;TIndexDef   

      *MethodIndex=ClientDataSet1-&gt;IndexDefs-&gt;AddIndexDef();</P>  

      <P class=Code>&nbsp;&nbsp;MethodIndex-&gt;Name&nbsp;&nbsp;&nbsp;=   

      "PaymentMethod"; </P>  

      <P class=Code>&nbsp;&nbsp;MethodIndex-&gt;Fields = "PaymentMethod"; </P>  

      <P class=Code>}</P>  

      <P class=BodyText> </P>  

      <P class=BodyText>One of these indexes must be activated when users click   

      a radio button. The <I style="mso-bidi-font-style: normal">selectIndex</I>   

      member function performs this task. The function looks at the selected   

      radio button and activates the corresponding index: </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>void</B> TForm1::SelectIndex()</P>  

      <P class=Code>{</P>  

      <P class=Code>&nbsp;&nbsp;<B> if</B> (btnItemsTotal-&gt;Checked) </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;ClientDataSet1-&gt;IndexName =   

      "ItemsTotal"; </P>  

      <P class=Code>&nbsp;&nbsp;<B> else</B></P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;ClientDataSet1-&gt;IndexName =   

      "PaymentMethod"; </P>  

      <P class=Code>}</P>  

      <P class=BodyText> </P>  

      <P class=BodyText>When the program starts, the two index objects need to   

      be created, and the current index for the ClientDataSet must be   

      initialized. This is done from the constructor of the main form. The   

      constructor first calls the <I>CreateIndices</I> method, which creates the   

      index objects. Next, the constructor calls the <I>SelectIndex</I> member   

      function to initialize the <I>IndexName</I> property of the ClientDataSet:   

      </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>__fastcall</B> TForm1::TForm1(TComponent* Owner) </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;: TForm(Owner) </P>  

      <P class=Code>{</P>  

      <P class=Code>&nbsp;&nbsp;CreateIndices();</P>  

      <P class=Code>&nbsp;&nbsp;SelectIndex();</P>  

      <P class=Code>}</P>  

      <P class=BodyText> </P>  

      <P class=BodyText>The last piece of the puzzle is the <I>OnClick</I> event   

      handlers for the radio buttons. When users click a radio button, the   

      program must sort the ClientDataSet based on the user's selections. This   

      is done through the <I>OnClick</I> event handlers for the radio buttons.   

      The <I>SortingChanged</I> method serves as the <I>OnClick</I> event   

      handler for both radio buttons. <I   

      style="mso-bidi-font-style: normal">SortingChanged</I> simply calls the <I   

      style="mso-bidi-font-style: normal">SelectIndex</I> method to activate the   

      correct index: </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>void</B> <B   

      style="mso-bidi-font-weight: normal">__fastcall</B>   

      TForm1::SortingChanged(TObject *Sender) </P>  

      <P class=Code>{</P>  

      <P class=Code>&nbsp;&nbsp;SelectIndex();</P>  

      <P class=Code>}</P>  

      <P class=BodyText> </P>  

      <P class=BodyText>Run the program and click the Open button to load the   

      data. Then click on one of the radio buttons to verify that the data is   

      sorted according to the radio button that you selected. Toggle the radio   

      buttons, and watch the data sorting change from one column to the next.   

      One of our original reasons for using an index to sort the data was to   

      make sure that users didn't lose their places in the grid when the sorting   

      order changed. Scroll through the grid and then toggle the radio button.   

      You should see that the grid doesn't lose its place when you change the   

      sort field. </P>  

      <P class=BodyText> </P>  

      <P class=Subheads>Example Two: Sorting a DBGrid</P>  

      <P class=BodyText>Example one demonstrated how to sort a dataset without   

      re-querying the database. Unfortunately, it only allows users to sort on   

      two of the columns in the dataset. It would be better if users could sort   

      based on any of the columns in the grid. Furthermore, the sorting should   

      occur when users click on one of the column headers instead of when they   

      click on a radio button. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText>In this example, we'll expand the first example to allow   

      sorting by any column in the dataset. To do this, we need to create one   

      index for every field in the dataset. We'll also nuke the radio buttons.   

      We'll sort the dataset when users click on the column header of the grid.   

      </P>  

      <P class=BodyText> </P>  

      <P class=BodyText><A   

      href="cb199910hh_f.asp.htm#ListingThree">Listing   

      Three</A> and <A   

      href="cb199910hh_f.asp.htm#ListingFour">Listing   

      Four</A> shows the code for this example. It's similar to the code for   

      example one; the main form still has a member function named   

      <I>CreateIndices</I>. Instead of just creating two <I>IndexDef</I>   

      objects, however, the new version of <I>CreateIndices</I> loops through   

      all the fields in the ClientDataSet and creates an <I   

      style="mso-bidi-font-style: normal">IndexDef</I> object for each of them   

      (see Figure 7). </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>void</B> TForm1::CreateIndices(TClientDataSet *dataset)   

      </P>  

      <P class=Code>{</P>  

      <P class=Code>&nbsp;&nbsp;<I> <SPAN class=CodeBlue>// Loop through the   

      fields in the dataset and create one</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// index for each field.   

      The index name will match the</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// field name. Note that   

      we skip</SPAN></I><I> <SPAN class=CodeBlue>calculated fields   

      because</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// calculated fields are   

      not stored in the dataset and</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// cannot be the basis   

      of an index. </SPAN></I></P>  

      <P class=Code>&nbsp;&nbsp;<B> int</B> nFieldCount =   

      dataset-&gt;FieldCount; </P>  

      <P class=Code> </P>  

      <P class=Code>&nbsp;&nbsp;<B> for</B> (<B>int</B> j=0; j &lt; nFieldCount;   

      ++j) </P>  

      <P class=Code>&nbsp;&nbsp;{ </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;TField *field =   

      dataset-&gt;Fields-&gt;Fields[j]; </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;AnsiString indexName =   

      field-&gt;FieldName; </P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;// Make sure   

      the index name doesn't already exist, and</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;// check if   

      the field is a calculated field. If the index</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;// doesn't   

      already exist, and the field isn't a</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;&nbsp;&nbsp;//   

      calculated field, then create a new index. </SPAN></I></P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;<B> if </B>(   

      (dataset-&gt;IndexDefs-&gt;IndexOf(indexName) == -1) &amp;&amp; </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;   

      (field-&gt;FieldKind != fkCalculated) ) </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;{ </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TIndexDef * index =   

      dataset-&gt;IndexDefs-&gt;AddIndexDef();</P>  

      <P   

      class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index-&gt;Name&nbsp;&nbsp;&nbsp;=   

      indexName; </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;index-&gt;Fields =   

      field-&gt;FieldName; </P>  

      <P class=Code>&nbsp;&nbsp;&nbsp;&nbsp;} </P>  

      <P class=Code>&nbsp;&nbsp;} </P>  

      <P class=Code>}</P>  

      <P class=Captions><B>Figure 7:</B> <I>CreateIndices</I> creating an   

      <I>IndexDef</I> object for ClientDataSet fields. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText><I>CreateIndices</I> loops through the <I   

      style="mso-bidi-font-style: normal">Fields</I> property of   

      <I>ClientDataSet1</I>. The function creates a <I>TIndexDef</I> object for   

      each field in the dataset. The name of the index is set to the   

      <I>FieldName</I> of the field. This naming convention will play a role   

      when we start working with the grid. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText>Note: The <I>CreateIndices</I> function loops through   

      the fields array before the dataset is opened. For this to work, you must   

      create persistent fields for the ClientDataSet. If you forget to add   

      persistent fields to the fields editor, then no fields will exist in the   

      fields array, and <I>CreateIndices</I> will fail to create the indexes. To   

      create persistent fields, double-click on the client dataset to bring up   

      the fields editor. Right-click on the fields editor to bring up a context   

      menu, and select the Add all fields menu option.</P>  

      <P class=BodyText> </P>  

      <P class=BodyText>Notice the second condition in the <B>if</B> statement.   

      We must ensure we don't attempt to create an index for calculated fields.   

      Calculated fields aren't stored in the dataset, so there's no way to sort   

      based on a calculated field. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText>Note: ClientDataSet supports a new type of calculated   

      field called an InternalCalc field. InternalCalc fields are stored with   

      the dataset, and you can create an index on an InternalCalc field. For   

      this reason, you should use InternalCalc fields instead of regular   

      calculated fields whenever you work with ClientDataSet. InternalCalc   

      fields aren't available in Table and Query components. </P>  

      <P class=BodyText> </P>  

      <P class=BodyText>Once the indexes are created, the foundation for sorting   

      the data is in place. Now all we need is code that sets the   

      <I>IndexName</I> property of <I>ClientDataSet1</I> based on the grid   

      column that users click. The best way to handle this task is to create an   

      <I>OnTitleClick</I> event for the DBGrid control. We set the index based   

      on the column that users clicked inside this event handler (see Figure 8).   

      </P>  

      <P class=BodyText> </P>  

      <P class=Code><B>void</B> <B   

      style="mso-bidi-font-weight: normal">__fastcall</B>   

      TForm1::DBGrid1TitleClick(TColumn *Column) </P>  

      <P class=Code>{</P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// The Column object is   

      the column the user clicked. </SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// TColumn provides a   

      Field property that gives us access</SPAN></I></P>  

      <P class=Code><I><SPAN class=CodeBlue>&nbsp;&nbsp;// to the TField for the   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -