July 2008 - Posts - Hilary Stoupa
in

InfoPath Dev

Hilary Stoupa

July 2008 - Posts

  • Take Two -- Mapping Data from Nested Repeating Tables to a SQL Database - DBXL v2.2

    In an earlier post, we looked at mapping data from nested repeating tables using DBXL v2.2. In that post, the SQL table associated with the main repeating form group used an identity column that was set to auto-increment for the key. DBXL, however, currently follows a delete and reshred model which would mean that our identity would change every time the document was updated.

    While this may not be an issue for some scenarios, there could be cases where you would prefer your identity to remain a bit more stable. One way to work around this is to use the DocId (generated by DBXL) for your key -- after all, that number remains the same for the life of the document. However, in our initial example, we have mapped a repeating group for the node path for our main table (Projects). We could have one to umpteen projects for a given DocId!

    I am sure there are many creative solutions to this problem, but only one occurred to me, and that is what I'd like to walk through in this post. What if we modify our Projects table to use a composite key consisting of the DocId and a ProjectId that identifies each project group in the document? We could do away with auto-incrementing completely. The foreign key on the Issues table would relate back to the DocId and ProjectId, and then, upon re-shredding, none of our identites will change.

    First, let's modify our form schema:
    Form with modified schema

    We've added a ProjectId field. The datatype is integer, and it has a default value of count(../preceding-sibling::my:Project/my:ProjectId) + 1 which will give us a running count of our groups -- the field's value will be 1 for the first group inserted, 2 for the second, and so forth.

    Now we need to modify our database. Add a column called ReportId (we'll map the DocId to it) to both the Projects and the Issues tables. In the Projects table, remove the Identity specification from the ProjectId column, as we'll now be mapping our new ProjectId field to that column.
    Projects Table with new column

    Issues Table with new column 

    We need to set ReportId and ProjectId as a composite key for the Projects table. While your table is open in design view, right click anywhere on the canvas and select Indexes/Keys:
    Right click menu

    When the Indexes/Keys window opens, you can select the button next to the Columns field in the General section and select the columns you wish to use for your composite key:
    Indexes Keys window

    Selecting columns

    Don't forget to modify the foreign key relationship with the issues table:
    Foreign Key for Issues Table

    To our mapping! We need to make a few changes -- we are going to map ResourceId to the DocId and ProjectId to ProjectId. When you select your columns from the Database Tree, your keys will be marked as such.
    Projects table mapped

    Don't forget -- special DBXL fields are available to you for mapping in the Schema Tree:
    Schema tree, DBXL

    Next, we adjust our Issues mapping to reflect our changes, first setting up our keys:
    Issues keys mapped

    And, after we add the rest of the Issues columns, our full map looks like this:
    Fully mapped form

    Let's cut to the fun part. We save our new mapping, and open our form, fill it out and submit it:
    Filled out Status Report

    When you look at the tables, you can see that our DocId is being used for ReportId and the new ProjectId field is providing a ProjectId:
    New Rows, Projects table

    And, in Issues, we are relating all of a project's issues back to it, as well as relating the issues to the report:
    New Rows, Issues table

    For greater database integrity, you could use the same approach as we used for Projects to provide the Issues group in the form an identity, and create an IssuesId column in your table. Your primary key for your Issues table could be a composite key consisting of ReportId, ProjectId and IssueId.

    We can now reopen our form that we just submitted and make some changes, as well as adding additional rows:
    Updated form

    Once again, we race to the database, happily clapping our hands, to make sure that all our identities remain unchanged and our new identities are what we would expect:
    Updated Projects Table

    Updated Issues Table

  • Mapping Data from Nested Repeating Tables to a SQL Database - DBXL v2.2

    Sometimes it seems that InfoPath form templates are like snowflakes -- no two are alike. I thought it might be helpful to have more samples of data mapping using DBXL, and figured I may as well try DBXL v2.2 (available for download on Qdabra.com). It's new -- I'm new -- we have a lot in common. I'm also using InfoPath 2007 and SQL Express 2005.

    For this sample, I've created a Status Report form (you can download a copy by right-clicking here and selecting "Save Target As..."). It has a repeating section for projects, with a nested repeating section for any issues. The main data source looks like this:
    Main Data Source

    The template has a straightforward design -- a repeating table bound to Project and an optional section bound to Issues with another repeating table bound to Issue.

    In design mode, the template looks like this:
    Design Mode

    And in preview:
    Preview Mode

    A couple of points -- my form is configured to submit to my DBXL webservice -- the sample available for download above is now. Also, we need to set up a database for the data we'll be mapping from our form. We want to be sure to use compatible data types when we do that. My form has several date fields that I'll want to map to datetime SQL columns. We also want to make sure that our columns are the correct size for the data we wish to insert. I asked David Airapetyan for some guidance on database design for mapping the other day and he said:

    As a rule of thumb, you want the data field size to be the maximum of what you expect the user to enter. For example, a phone number will unlikely be more than 30-40 characters even with spaces, country codes and extensions.

    The task of picking the data field size is not trivial. For example, some people have very long names that can break your expectations. When you set up DBXL shredding and the actual field size is greater to what you have specified in the database, a shredding error will occur. One best practice to avoid those issues is to set the maximum textbox length in InfoPath to match your column size in the database.

    So, when you create your database column size, if your fields in your form do not have limits, you may want to set them. If you can't change your form, you may want increase your column size.

    Because of my two repeating groups, I plan to create two tables. I'm naming my datbase StatusReports and my tables Projects and Issues. My Projects table looks like this:
    Projects table design

    And my Issues table:
    Issues table design

    I have given my table columns the same names as my form fields. That is not required, but I lack imagination. Note that I added an ID column (ReportId) to my table that isn't related to a field in my form. I set ReportId as my primary key in my Projects table -- I also set it as an identity so that it would auto-increment:
    Identity for Projects table

    Finally, I created a foreign key relationship between my Issues table and my Projects table on ReportId. While not necessary for the form to shred correctly, it is always a good idea to make those table relationships formal.
    Foreign key relationship creation

    Now that my database is set up, I'll publish my form and attach it to the DBXL Administration Tool for my DBXL installation (DAT).

     First, open DAT, and select New Configuration:
    New Configuration button

    Then name your configuration and attach your published form:
    DAT General Tab

    Select the Database tab:
    DAT Database Tab

    We need to fill in the Connection String field. The connection string, if you wish to use integrated authentication, is written thus: Integrated Security=SSPI;Data Source=<server>;Initial Catalog=<database>  with <server> and <database> replaced with the name of your server and your database. For SQL Authentication, the connection string would be: Data Source=<server>;Initial Catalog=<database>;User Id=<userId>;Password=<password> with, of course, <userId> and <password> replaced with your information.

    You'll see a Test Connection button after you tab out of the Connection String field -- be sure to give it a click:
    Test Connection Button

    A message box will pop up and tell you if your connection was successful. If it fails, the reason for failure will display. When your test succeeds, save your configuration before proceeding to the next steps.

    Click Insert Table or Column under the Database Map section to add a section for our Projects table:
    Add Table

    Note the Select Database Table button at the right of the Table Name field. Click it and the Database Tree opens in the taskpane:
    Database Tree

    If you double-click Projects in the Database Tree, the Table Name field will populate:
    Table Field

    Now, in the Node Path field next to the Table Name, click the Select Schema Node button, which opens the Schema Tree:
    Schema Tree

    Double-click the node associated with the first repeating group (my:Project) to populate the Node Path field:
    Node Path field

    To start adding our columns, select the top Insert Table or Column directly under the Table Name field.
    Type field

    For Type, select Column and map a column to a field in your form. You can type in the column name, of course, but if you select it from the Database Tree, the DB Type is selected for you. Also, it is more fun. The Node Path, too, can be typed in or selected from the Schema Tree. Needless to say, you can XPath up that Node Path all you want, which is good news since I have two fields in my form that I'd like to map that are not children of the table level Node Path.
    Column Mapping

    After mapping all the fields to our Projects table, the map looks like this:
    Projects table mapped

    That was almost too easy. Good news, adding the Issues table will be even more straighforward! Select Insert Table or Column directly under Description (as if adding another column) and for Type select Table:
    Add child table

    The Table Name will be Issues and the Node Path will be my:Projects/my:Project/my:Issues/my:Issue (note that the Node Path is to the nested repeating group). Select Insert Foreign Key below Column Name and put the ReportId column from the Issues table into the Column Name field and the ReportID column from the Projects table into the Parent Column Name field:
    Foreign Key Mapping

    All that is left to do is map those Issues columns to the fields in the Issue group. Select Insert Table or Column directly below Insert Foreign Key to add columns:
    Issues table mapped

    Our completed mapping:
    Full Map

    We are all done with mapping. Save your configuration, return to the form Catalog, and fill out your Status Report. I am going to put in three different projetcts, and add several issues to one project:
    Filled out form

    Now, submit the form and gleefully run off and check your SQL Tables -- I'll do the same.
    Projects Table with Data

    Issues table with dat

  • InfoPath 2007 features that are unavailable in InfoPath Forms Services

    I came across a nice article on Office Online that explains the controls and features available in InfoPath 2007 that are not available in InfoPath Forms Service. It may be helpful when making design decisions for a form that needs to be Forms Service compatible.

    InfoPath 2007 features that are unavailable in InfoPath Forms Services

  • How Do I Copy Repeating Data From an External Source into My Form?

    Upon occasion you may need to copy external data into form fields bound to the form's Main Data Source. In this sample for InfoPath 2007, we will create a form with nested repeating tables and using code copy our external data to the appropriate tables. Our scenario is a selection of vehicles, grouped by type (Sports Cars, Luxury Cars, etc) with an array of dealers for each specific vehicle. All files used in this sample are available here: Copy Repeating External Data Into a Form

    Sample Form Schema

    The sample form schema for the main data source looks like this:

    Main Data Source

    Secondary Data Sources 

    We need two XML files that we will add as secondary data connections. The first is the Vehicles.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <vehicles>
      <vehicle>
        <TypeId>1</TypeId>
        <VehicleType>Sports Cars</VehicleType>
        <VehicleId>1</VehicleId>
        <VehicleYear>1968</VehicleYear>
        <VehicleMake>Chevrolet</VehicleMake>
        <VehicleModel>Corvette</VehicleModel>
        <VehicleColor>Red</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>1</TypeId>
        <VehicleType>Sports Cars</VehicleType>
        <VehicleId>2</VehicleId>
        <VehicleYear>2004</VehicleYear>
        <VehicleMake>Dodge</VehicleMake>
        <VehicleModel>Viper</VehicleModel>
        <VehicleColor>Red</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>1</TypeId>
        <VehicleType>Sports Cars</VehicleType>
        <VehicleId>3</VehicleId>
        <VehicleYear>2007</VehicleYear>
        <VehicleMake>Ferrari</VehicleMake>
        <VehicleModel>599 GTB</VehicleModel>
        <VehicleColor>Red</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>1</TypeId>
        <VehicleType>Sports Cars</VehicleType>
        <VehicleId>4</VehicleId>
        <VehicleYear>1978</VehicleYear>
        <VehicleMake>Pontiac</VehicleMake>
        <VehicleModel>Trans Am</VehicleModel>
        <VehicleColor>Black</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>2</TypeId>
        <VehicleType>Classic Cars</VehicleType>
        <VehicleId>5</VehicleId>
        <VehicleYear>1924</VehicleYear>
        <VehicleMake>Ford</VehicleMake>
        <VehicleModel>Model T</VehicleModel>
        <VehicleColor>Black</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>3</TypeId>
        <VehicleType>Trucks</VehicleType>
        <VehicleId>6</VehicleId>
        <VehicleYear>1990</VehicleYear>
        <VehicleMake>Dodge</VehicleMake>
        <VehicleModel>Ram</VehicleModel>
        <VehicleColor>Blue</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>3</TypeId>
        <VehicleType>Trucks</VehicleType>
        <VehicleId>7</VehicleId>
        <VehicleYear>2006</VehicleYear>
        <VehicleMake>Ford</VehicleMake>
        <VehicleModel>F250</VehicleModel>
        <VehicleColor>Pewter</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>3</TypeId>
        <VehicleType>Trucks</VehicleType>
        <VehicleId>8</VehicleId>
        <VehicleYear>2008</VehicleYear>
        <VehicleMake>GMC</VehicleMake>
        <VehicleModel>3500</VehicleModel>
        <VehicleColor>Green</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>4</TypeId>
        <VehicleType>Luxury Cars</VehicleType>
        <VehicleId>9</VehicleId>
        <VehicleYear>2009</VehicleYear>
        <VehicleMake>Rolls-Royce</VehicleMake>
        <VehicleModel>Phantom Coupe</VehicleModel>
        <VehicleColor>Silver</VehicleColor>
      </vehicle>
      <vehicle>
        <TypeId>4</TypeId>
        <VehicleType>Luxury Cars</VehicleType>
        <VehicleId>10</VehicleId>
        <VehicleYear>2009</VehicleYear>
        <VehicleMake>Cadillac</VehicleMake>
        <VehicleModel>CTS</VehicleModel>
        <VehicleColor>Tan</VehicleColor>
      </vehicle>
    </vehicles>

    The second is Dealers.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <dealers>
      <dealer>
        <VehicleId>1</VehicleId>
        <DealerId>dlr_cw</DealerId>
        <DealerName>Cal Worthington</DealerName>
      </dealer>
      <dealer>
        <VehicleId>1</VehicleId>
        <DealerId>dlr_kp</DealerId>
        <DealerName>Kirkland Pontiac</DealerName>
      </dealer>
      <dealer>
        <VehicleId>2</VehicleId>
        <DealerId>dlr_pd</DealerId>
        <DealerName>Penrose Dodge</DealerName>
      </dealer>
      <dealer>
        <VehicleId>2</VehicleId>
        <DealerId>dlr_sf</DealerId>
        <DealerName>Sommerset Ford</DealerName>
      </dealer>
      <dealer>
        <VehicleId>2</VehicleId>
        <DealerId>dlr_wd</DealerId>
        <DealerName>Wilconson Dodge</DealerName>
      </dealer>
      <dealer>
        <VehicleId>4</VehicleId>
        <DealerId>dlr_kp</DealerId>
        <DealerName>Kirkland Pontiac</DealerName>
      </dealer>
      <dealer>
        <VehicleId>5</VehicleId>
        <DealerId>dlr_sf</DealerId>
        <DealerName>Sommerset Ford</DealerName>
      </dealer>
      <dealer>
        <VehicleId>6</VehicleId>
        <DealerId>dlr_pd</DealerId>
        <DealerName>Penrose Dodge</DealerName>
      </dealer>
      <dealer>
        <VehicleId>6</VehicleId>
        <DealerId>dlr_wd</DealerId>
        <DealerName>Winconson Dodge</DealerName>
      </dealer>
      <dealer>
        <VehicleId>7</VehicleId>
        <DealerId>dlr_af</DealerId>
        <DealerName>Allen Ford</DealerName>
      </dealer>
      <dealer>
        <VehicleId>7</VehicleId>
        <DealerId>dlr_pjf</DealerId>
        <DealerName>Penny-James Ford</DealerName>
      </dealer>
      <dealer>
        <VehicleId>7</VehicleId>
        <DealerId>dlr_sf</DealerId>
        <DealerName>Sommerset Ford</DealerName>
      </dealer>
      <dealer>
        <VehicleId>8</VehicleId>
        <DealerId>dlr_kp</DealerId>
        <DealerName>Kirkland Pontiac</DealerName>
      </dealer>
      <dealer>
        <VehicleId>8</VehicleId>
        <DealerId>dlr_spbg</DealerId>
        <DealerName>Seaview Pontiac Buick GMC</DealerName>
      </dealer>
      <dealer>
        <VehicleId>9</VehicleId>
        <DealerId>dlr_bhrr</DealerId>
        <DealerName>Beverly Hills Rolls-Royce</DealerName>
      </dealer>
      <dealer>
        <VehicleId>9</VehicleId>
        <DealerId>dlr_vrr</DealerId>
        <DealerName>Vegas Rolls-Royce</DealerName>
      </dealer>
      <dealer>
        <VehicleId>10</VehicleId>
        <DealerId>dlr_fc</DealerId>
        <DealerName>Florida Cadillac</DealerName>
      </dealer>
      <dealer>
        <VehicleId>10</VehicleId>
        <DealerId>dlr_kp</DealerId>
        <DealerName>Kirkland Pontiac</DealerName>
      </dealer>
      <dealer>
        <VehicleId>10</VehicleId>
        <DealerId>dlr_spbg</DealerId>
        <DealerName>Seaview Pontiac Buick GMC</DealerName>
      </dealer>
      <dealer>
        <VehicleId>10</VehicleId>
        <DealerId>dlr_vsc</DealerId>
        <DealerName>Vegas Strip Cadillac</DealerName>
      </dealer>
    </dealers>

    As you can see, there is a one to many relationship between the xml files. Each vehicle may have any number of dealers.

    Sample Form Construction

    Create a new form with a schema like that shown in the Sample Form Schema section. Add the two XML files as resource files:

    1. Select Resource Files from the Tools menu
    2. Select the Add button in the Resource Files window
    3. Browse the Vehicles.xml file and select the OK button
    4. Repeat for the Dealers.xml and select the OK button in the Resource Files window to close

    Now create two secondary data connections using the resource files:

    1. Select Data Connections from the Tools menu
    2. Select the Add button in the Data Connections window
    3. Select Create a new connection to:
    4. Select Receive data
    5. Select the Next button
    6. Select XML document for the source of the data
    7. Select the Next button
    8. Select the Resource Files button
    9. Select the Dealers.xml file that you added to the Resource Files in the section above
    10. Select the OK button
    11. Select the Next button
    12. Select the Finish button
    13. Repeat these steps to add a data connection to the Vehicles.xml

    In your form, add a drop-down list box bound to the selectedType node in the main data source. The values for the drop-down should be provided by the VehicleType nodes in the Vehicles data connection:

    1. Under List box entries in the properties for the drop-down list box, select Look up values from an external data source
    2. Select Vehicles from the Data source drop-down list box
    3. Select the button next to Entries to open the Select a Field or Group window
    4. Select the VehicleType node
    5. Select the OK button
    6. Select Show only entries with unique display names
    7. Select the OK button

    You can preview your form and check that your drop-down is correct:

    Add a repeating table connected to Vehicle in the main data source, and a field that will display dealer information in a repeating section in that table.

    Add a button with the label "Add Rows". We will use it to run our code for copying our data. The finished form should look something like this:

    Form Code

    Right-click the Add Rows button, and, under Button Properties, select the Edit Form Code button.

    Microsoft Script Editor or VSTA will open, depending on what programming language your form is using (this can be changed under Tools/Options/Programming).

    In JScript, the following code for the button OnClick event will copy data from Vehicles.xml and Dealers.xml into the tables on your form:

    // Get the selected vehicle type.
     var selectedType = XDocument.DOM.selectSingleNode("/my:myFields/my:selectedType").text;

     // If no form was selected notify the user.
     if(selectedType == "")
     {
      XDocument.UI.Alert("Please select a vehicle type first.");
      return;
     }
     
     // Get the list of vehicles per the selected vehicle type.
     var vehicles =XDocument.GetDOM("Vehicles").selectNodes("/vehicles/vehicle[VehicleType = '" + selectedType + "']");

     // If nothing was found, then return; there will be no items to insert. 
     if(vehicles == null)
      return;
      
     // Get the Vehicle insertion point.
     var vehicleList = XDocument.DOM.selectSingleNode("/my:myFields/my:Vehicles");

     // Add the rows to the main DOM.
     var vehicle;
     while(vehicle = vehicles.nextNode())
     {
      try
      {
       // Get this vehicle's values from the secondary DOM.
       var vehicleId = vehicle.selectSingleNode("VehicleId").text;
       var year = vehicle.selectSingleNode("VehicleYear").text;
       var make = vehicle.selectSingleNode("VehicleMake").text;
       var model = vehicle.selectSingleNode("VehicleModel").text;
       var color = vehicle.selectSingleNode("VehicleColor").text;

       // Build a string representing a main DOM vehicle nodeset using the values from the secondary DOM.
       var vehicleXml = "<my:Vehicle xmlns:my='http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-06-03T00:09:57'>"
           + "<my:Year>" + year + "</my:Year>"
           + "<my:Make>" + make + "</my:Make>"
           + "<my:Model>" + model + "</my:Model>"
           + "<my:Color>" + color + "</my:Color>"
           + "<my:Dealers>";

       // Get the list of Dealers for this vehicle.
       var dealers =  XDocument.GetDOM("Dealers").selectNodes("/dealers/dealer[VehicleId = '" + vehicleId + "']");

       // Add the dealer rows to the XML.
       var dealer;
       while(dealer = dealers.nextNode())
       {
        var dealerId = dealer.selectSingleNode("DealerId").text;
        var dealerName = dealer.selectSingleNode("DealerName").text;
        
        vehicleXml += "<my:Dealer>"
           + "<my:DealerId>" + dealerId + "</my:DealerId>"
           + "<my:DealerName>" + dealerName + "</my:DealerName>"
           + "</my:Dealer>";
       }

       vehicleXml += "</my:Dealers></my:Vehicle>"

       // Load new vehicle string into a temporary XML DOM.
       var domNewRow = XDocument.CreateDOM();
       domNewRow.validateOnParse = false;
       domNewRow.async = false;
       domNewRow.loadXML(vehicleXml);
       domNewRow.setProperty("SelectionNamespaces", 'xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-06-03T00:09:57%22');
       
       // Insert the new vehicle into the main DOM.
       vehicleList.appendChild(domNewRow.selectSingleNode("my:Vehicle"));
      }
      catch(ex)
      {
       XDocument.UI.Alert("Could not insert vehicle row.\n\nError message:\n" + ex.Message);
      }
     }

    And, for C#, you can use this code in your button's Clicked event:

    // Get the selected vehicle type.
    string selectedType = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:selectedType", NamespaceManager).Value;

    // If no form was selected notify the user.
    if (selectedType.Equals(""))
    {
        MessageBox.Show("Please select a vehicle type first.");
        return;
    }

    // Get the list of vehicles per the selected vehicle type.
    XPathNodeIterator vehicles = this.DataSources["Vehicles"].CreateNavigator().Select("/vehicles/vehicle[VehicleType = '" + selectedType + "']", NamespaceManager);

    // If nothing was found, then return; there will be no items to insert.
    if (vehicles.Count == 0)
    {
        return;
    }

    //Get the Vehicle insertion point.
    XPathNavigator vehicleList = MainDataSource.CreateNavigator().SelectSingleNode("/my:myFields/my:Vehicles", NamespaceManager);

    //Add the rows to the main DOM.
    foreach (XPathNavigator vehicle in vehicles)
    {
        try
        {
            // Get this vehicle's values from the secondary DOM.
            string vehicleId = vehicle.SelectSingleNode("VehicleId", NamespaceManager).Value;
            string year = vehicle.SelectSingleNode("VehicleYear", NamespaceManager).Value;
            string make = vehicle.SelectSingleNode("VehicleMake", NamespaceManager).Value;
            string model = vehicle.SelectSingleNode("VehicleModel", NamespaceManager).Value;
            string color = vehicle.SelectSingleNode("VehicleColor", NamespaceManager).Value;

            // Build a string representing a main DOM vehicle nodeset using the values from the secondary DOM.
            string vehicleXml = "<my:Vehicle xmlns:my='http://schemas.microsoft.com/office/infopath/2003/myXSD/2008-06-03T00:09:57'>"
                            + "<my:Year>" + year + "</my:Year>"
                            + "<my:Make>" + make + "</my:Make>"
                            + "<my:Model>" + model + "</my:Model>"
                            + "<my:Color>" + color + "</my:Color>"
                            + "<my:Dealers>";

            // Get the list of Dealers for this vehicle.
            XPathNodeIterator dealers = this.DataSources["Dealers"].CreateNavigator().Select("/dealers/dealer[VehicleId = '" + vehicleId + "']", NamespaceManager);

            // Add the dealer rows to the XML.
            foreach (XPathNavigator dealer in dealers)
            {
                string dealerId = dealer.SelectSingleNode("DealerId", NamespaceManager).Value;
                string dealerName = dealer.SelectSingleNode("DealerName", NamespaceManager).Value;

                vehicleXml += "<my:Dealer>"
                            + "<my:DealerId>" + dealerId + "</my:DealerId>"
                            + "<my:DealerName>" + dealerName + "</my:DealerName>"
                            + "</my:Dealer>";
            }

             vehicleXml += "</my:Dealers></my:Vehicle>";

            //Load new vehicle string into a temporary XML document
            XmlDocument tempDoc = new XmlDocument();
            tempDoc.LoadXml(vehicleXml);

            // Insert the new vehicle into the main DOM.
            XPathNavigator newVehicle = tempDoc.CreateNavigator().SelectSingleNode("my:Vehicle", NamespaceManager);
            vehicleList.AppendChild(newVehicle);
        }
        catch (Exception ex)
        {
            MessageBox.Show("Could not insert vehicle row.\n\nError message:\n" + ex.Message);
        }
    }

    Your form is now ready to try. Preview it, select a vehicle type from the drop-down list box, select the Add Rows button, and your repeating tables should populate with the correct data from your secondary data sources.

Copyright © 2003-2017 Qdabra Software. All rights reserved.
View our Terms of Use.