MOSSIG follow up SharePoint installer project from Codeplex

Hey everyone as promised here is the link to the SharePoint web Part project template for Visual Studio 2008 that I showed last night.

Also don’t forget Will mentioned that a full VSE for Visual Studio 2008 is due out in the next couple of months. I’ll do my best to put up link to this as soon as I know more.

 

Finally a big thanks to all who attended and presented last night, and don’t forget to checkout MOSSIG.Net for all details on upcoming presentations and news.

Technorati Tags: ,,,

Filtered Drop Down Lists 101 Part 2

Now for the long awaited second half of my post on working with Filtered Drop down lists.

In my first post I showed you how to created filtered drop down lists using the InfoPath rich client. In this post I will show you how to achieve the same functionality in a web based form.

The biggest draw back about creating this functionality in a web based form is that filtered fields are not supported in web based forms. So we need to create another means to filter our data, an external data source like a web service for example provides us with this ability as all the filtering can be done using code and then returned to the InfoPath form via a data connection.

In my last post I used a set of data based around car manufactures and models. I’ll use the same data for this example. This doesn’t mean that only an XML file can be used to source this data there is no reason why you couldn’t use SQL or another database as a data store to source your data.

For this post I’m going to create a reasonably basic web service that contains 3 web methods. The first will return a list of car manufactures, the second will return a list of car models for the supplied manufacturer, and the third method will return a list of available colours for the selected Manufacturer/Model combination.

Method 1

/// <summary>
    /// This method returns a list of car manufacturers
    /// </summary>
    /// <returns></returns>
    [WebMethod]
    public string[] GetCarManufacurer() 
    {
        //Create an xml document to hold the list of cars
        XmlDocument carList = new XmlDocument();
        
        //Load the car list into the XmlDocumentObject
        carList.Load("http://localhost/FilteredDropdown/Reference%20Files/Cars.xml");

        //Create xmlNode list to hold a list of the manufacturers
        XmlNodeList carMakers = carList.SelectNodes("//Cars/Car");

        //create a string array to retun a list of car manufacturers
        string[] returnString = null;

        if(carMakers.Count >0 && carMakers != null)
        {
            returnString = new string[carMakers.Count];

            //Create a counter interger to track where we are in the colleciton
            int counter = 0;

            //Take each car node in the collection and add the Make child node to the string array
            foreach (XmlNode car in carMakers)
            {
                returnString[counter] = car.SelectSingleNode("Make").InnerText;
                counter ++;
            }
        }

        //return the string array
        return returnString;
    }

Method 2

 /// <summary>
    /// This method will return a list of Car Models for the provided Make or manufacturer
    /// </summary>
    /// <param name="Make"></param>
    /// <returns></returns>
    [WebMethod]
    public string[] GetModelList(string Make)
    {
        //Create an xml document to hold the list of cars
        XmlDocument carList = new XmlDocument();

        //Load the car list into the XmlDocumentObject
        carList.Load("http://localhost/FilteredDropdown/Reference%20Files/Cars.xml");

        //Create xmlNode list to hold a list of the models for the supplied manufacturer
        XmlNodeList carModels = carList.SelectNodes("//Cars/Car[Make=\"" + Make + "\"]");

        //create a string array to retun a list of car manufacturers
        string[] returnString = null;

        if (carModels.Count > 0 && carModels != null)
        {
            returnString = new string[carModels.Count];

            //Create a counter interger to track where we are in the colleciton
            int counter = 0;

            //Take each car node in the collection and add the Make child node to the string array
            foreach (XmlNode car in carModels)
            {
                returnString[counter] = car.SelectSingleNode("Model").InnerText;
                counter++;
            }
        }

        //return the string array
        return returnString;
    }


Method 3

 /// <summary>
    /// This method will return a list of available colorus for the provided model/Make combination
    /// </summary>
    /// <param name="Model"></param>
    /// <returns></returns>
    [WebMethod]
    public string[] GetAvailableColors(string Model, string Make)
    {
        //Create an xml document to hold the list of cars
        XmlDocument carList = new XmlDocument();

        //Load the car list into the XmlDocumentObject
        carList.Load("http://localhost/FilteredDropdown/Reference%20Files/Cars.xml");

        //Create xmlNode list to hold a list of the models for the supplied manufacturer
        XmlNodeList carColors = carList.SelectNodes("//Cars/Car[Model=\"" + Model + "\" and Make= \"" + Make + "\"]");

        //create a string array to retun a list of car manufacturers
        string[] returnString = null;

        if (carColors.Count > 0 && carColors != null)
        {
            returnString = new string[carColors.Count];

            //Create a counter interger to track where we are in the colleciton
            int counter = 0;

            //Take each car node in the collection and add the Make child node to the string array
            foreach (XmlNode car in carColors)
            {
                returnString[counter] = car.SelectSingleNode("Color").InnerText;
                counter++;
            }
        }

        //return the string array
        return returnString;
    }

 


With the web service out of the way we now need to setup our InfoPath form to use it. First we’ll design a new blank form in InfoPath, making sure the “Enable browser compatible features only” option is checked.


image


 


With our blank form created we now need to define our data structure like the one below, you’ll notice that I have plural duplicates of the same node so I have a Make node and a Makes node, the plural node will be used to store the items returned from the web service. This allows for different entries in the “Cars” repeating list to have different items in their drop down lists.


image


Now remember anything that has a plural name should have the repeating box ticked


Next we’ll lay out our controls on the form right click on the “Cars” group and select “Repeating Table” you should end up with a table that looks like this


image


Now this is pretty ugly and to be honest we don’t need the “List” columns so removed those columns and change each of the remaining text boxes to drop down lists.


You should have a table should look like this


image


With our form setup we now need to hook up our web service to return the data we need for this we’ll need a couple of Data Connections.


From the “Tools” menu select “Data Connections” this will display the “Data Connections” window


image


image


Click the Add button to start the “Data Connection” wizard, for our first connection we want to retrieve a list of Car Manufacturers so select the Create New Connection to Receive data radio button. Then click the next button


image


Now we want to pull the data from the web service we created earlier so select the Web Service radio button the click next


image


Enter the name url of your web service then click Next


image


 


InfoPath will then attempt to interrogate the WSDL for the web to determine the methods available. This will then present you with a list of available web methods to use, as we want to get a list of car Manufacturers we’ll select GetCarManufacturer then click Next


image


For this example we are not going to store a copy of the InfoPath data with the form as it may change, but you may in your implementation prefer to store the data with the form to reduce trips to the server. For now simply click next to continue to the next step.


image


In the final step we can set when the data connection is queried and the name of the connection. This step however is usually overlooked and hence becomes a source of performance issues latter on. Be sure to check to see if you really need the data loaded automatically, as this can increase the load time of the form especially if there are multiple connections that need to be queried. For now we’ll accept the defaults and click the finish button as we want this data to be returned each time the form is loaded. Click close to close the “Data Connections” window


image 


 


With our first data connection created we can now hook up our first drop down list to the GetCarManufacturer method. Right click on the “Make” drop down list and select “Drop Down List Box Properties”. This will display the properties window for the drop down list box.


image image


First thing we need to do is rename the field to be something a little more intuitive. So change the Field name to “Make” to match our title in the designer.


Next we need to make the drop down list source its data from the data connection we created earlier. So from the “List Box Entries” section select the “Look up values from an external data source” radio button. By default InfoPath will select the first available data connection as we only have one available this is the one we want to use. With our data connection selected we now need to select the field that is going to be used in the drop down. Click on the “Edit Xpath” button next to the entries text box.


image


This will open the select field or group dialog, from here we can select the returned string array as the source for our drop down list. Then click “OK” to close the “Select a Field or Group” dialog.


image


On the properties dialog make sure the”Show only entries with unique name” check box is ticked the click ok to close the properties dialog.


With the “Make” drop down list setup we now need to add some code behind the “Changed” this code will execute the second data connection “GetModelList”lets move on to the “Model” drop down. First we need to create a new Data connection to return a list of car model. Open the Data Connections dialog via the tools menu, and click the “Add” button to to start the Data Connection wizard.


Create a new connection to receive data


image


Select “Web Service” as the data source


image


Enter the address of the web service we used earlier and click next


image


Select the “GetModelList” web method then click next


image


On the next screen we need to provide a sample value for InfoPath to query the web method we have selected. This allows InfoPath to determine the XML that will be returned from the web service ahead of time. Which in turn allows us to map our drop down to the returned results. For this example click on the set value button enter “Ford” then click ok. Finally click next to move to the next step.


image


As this data will change each time we use the form there is no need to store the data with the form so click next to progress past this screen


image


Lastly we don’t want this data source to be queried when the form is loaded as we will not have a valid parameter to pass to it so clear the “Automatically retrieve data when form is opened” Check box and click “Finish”


image


Now we have our second data connection to return our Model data setup we need to add a rule to our Make drop down to copy the selected Make into the GetModelList connection and run the query when. Open the properties for the Make drop down list and click on the “Rules…” button


image


Click on the “Add…” button to add a new rule to the list


image


Name the rule “Get Model List” then click on the “Set Condition…” button


image


Basically we only want this rule to run when the “Make” drop down is not blank so select “Is not blank” from the second drop down then click ok


image


Add a new action to set a fields value, as we need to pass in the selected make to the web service before it can be queried


image


Now the field we want to set is the query parameter of the GetModelList connection we made earlier so click on the “Select Field” button next to the field text box to select the appropriate field.


image


Click ok to close the “Select a Field or Group” window and return to the action window. Click on the FX button next to the “Value” text box to set the value that will be provided to the web service. Then enter a full stop in the “Insert Formula” window (A full stop is XPath shorthand and represents the current node) then click ok to close the “Insert Formula” window


image


Click ok once more to close the “Action” window we should now have an “Rule” window with one action listed


image


Click the “Add Action…”button once more to add another action, now that we have set the value to be passed in we can now execute the data connection to get a list of returned results.


Select “Query Using Data Connection” from the action drop down then select “GetModelList” from the Data connection drop down and click ok.


image 


You should now have a rule that looks similar to the following


image


Click ok to save the changes


Now that the the filtered data has been queried we need to store it in the form, we need to do this so we don’t get data inconsistencies when we add a new row to the repeating section.


First right click on the GetMake Drop down and select Programming>Changed


image


This will add a new event handler to the code that will execute after the value has been changed and also after any rules have been processed. So by the time this code executes the new values would have been selected and the GetModelList data connection should have been run. What the code now needs to do is to fill the ModelList/Models nodes with the models that were returned from the web service.


Model Population code

//If no models were returned then don't attmept to fill the list
if (getModels.SelectSingleNode("/dfs:myFields/dfs:dataFields/tns:GetModelListResponse/tns:GetModelListResult/tns:string", this.NamespaceManager) != null) 
{
    //Check for any existing entries that may have been carried over from the previous row
    if (currentRow.Select("../my:ModelList/my:Models",this.NamespaceManager).Count > 1)
    {
        currentRow.SelectSingleNode("../my:ModelList/my:Models[2]", this.NamespaceManager).DeleteRange(currentRow.SelectSingleNode("../my:ModelList/my:Models[last()]", this.NamespaceManager));
        currentRow.SelectSingleNode("../my:ModelList/my:Models[1]", this.NamespaceManager).SetValue("");
    }

    //Loop through each of the models returned and add them to the ModelList/Models node
    foreach (XPathNavigator model in getModels.Select("/dfs:myFields/dfs:dataFields/tns:GetModelListResponse/tns:GetModelListResult/tns:string", this.NamespaceManager))
    {
        //If the first node hasn't been set then set it with the first model returned
        if (currentRow.SelectSingleNode("../my:ModelList/my:Models", this.NamespaceManager).Value == string.Empty)
        {
            currentRow.SelectSingleNode("../my:ModelList/my:Models", this.NamespaceManager).InnerXml = model.InnerXml;
        }
        else //clone the last node in the list update it's value then insert the updated node at the end of the list
        {
            XPathNavigator newModel = currentRow.SelectSingleNode("../my:ModelList/my:Models[last()]", this.NamespaceManager).Clone();
            newModel.InnerXml = model.InnerXml;
            currentRow.SelectSingleNode("../my:ModelList/my:Models[last()]", this.NamespaceManager).InsertAfter(newModel);
        }
    }
}

Now that the models are being populated we can hook up the datasource for our Models Drop down list, switch back to the form designer and right click the models drop down and select properties


image


Select the “Look up values in the forms data source” option then for the entries value select the “Models” repeating node under the “ModelsList” group


image 


Make sure you check the “Show Only entries with unique display names” then click ok to save your changes


Now run your form to test your changes, you should find that when you select a make the model list automatically becomes populated with the data from the web service, plus because we are storing the returned data in the form if a new row is added the returned data is duplicated from row to row


image


image


 


image


 


image


Now I’ve left the code for setting the colour up out on purpose consider it a little challenge to make sure you can understand the concepts.


However I’m not completely heartless, if you want the complete solution you can always download it from here



you should note however this solution was created in Visual Studio 2008 so you may have to play around to get it running Visual Studio 2005, if I get time I’ll put up a second copy for everyone stuck on old tech :o)


 


Update: Thank you all for your comments, I’ve updated the code sample that was loaded to skydrive the InfoPath project is now included go forth and download :o)

Using the Content Query Web part on MySite

So I was out on client site today attempting to setup the content query web part on a MySite, after exporting the web part and re-importing it to the my site I then got a “Could not load XSL file. The system cannot find the file specified” error. After google failed to provide me an answer I decided to have a play around with the site settings for the MySite and found that if I enabled the “Office SharePoint Server Publishing Infrastructure” site collection features the content query web part started working like a charm. Not only that but if I deactivated the feature afterwards the web part would continue to function normally

MOSSIG Agenda for 27th Feb

So as promised here is the agenda for the upcoming MOSSIG meeting on the 27th of Feb, be sure to head on over to the MOSSIG site and register so we have an idea of catering requirements

Ben Walters – “Developing Web Parts using Visual Studio 2008 and the Web Part Template Project”

SDM

Ben will be showing you how to develop Web Parts for SharePoint2007 quickly and easily using the Web Part Template project from Codeplex.

Tim Wragg – ‘Adventures in the SharePointDesigner’

Professional Advantage

The SP Designer is one of the great unknowns with little help and guidance available.

In this session, Tim will help crack open some of its great features and take us through a recent implementation of the Sanctuary Lakes site which incorporates Forms Authentication and integrations with Dynamics CRM and Great Plains – all done through the Designer!.

Chris O’Connor – Visio Integration with SharePoint – using K2 Workflow’s

SDM

Chris will present the new Visio 2007 product, focusing on integrating list data from SharePoint for flowcharting, and viewing workflow tasks graphically.  The demo will also focus on the new K2[black pearl]workflow tool, with the Visio designer used to create SharePoint workflow’s without the need for any coding or programming skills required.

 

Also Microsoft Developer Evangelist Andrew Coates contacted us with some awesome news for members who might be interested in sitting certification exams. Microsoft is launching a new certification offer to all User Group members (including MOSSIG members) to encourage MCP / MCTS certification.

This is an opportunity for you to save some money on exams and for the MOSSIG group a chance to win $3000.- worth of goodies to give away.

Here’s what Andrew had to say:

“* We’re making it attractive for UG members to get certified – We’ve got 100 free exam vouchers for UG members who get an MCP or MCTS cert between now and May 31 (pass 1, get 1 free)

* We’re making it competitive between User Groups – the UG with the highest number of MCTS/MCP certifications passed between now and May 31 get a $3000-worth hamper of SWAG to distribute”

For full details head on over to: http://technet.microsoft.com/en-au/cc182196.aspx

Happy Chinese New Year!

 

Welcome to the Year of the Rat!

So I missed the usual Happy New Year post this year, and to top it off by the time I noticed it was too late to redeem myself so I figured why not wait until Chinese New Year to start my blog off for 2008.

Only a month an a half in to 2008 and so much has happened already here’s a quick run down

  • SDM was brought out by DWS
  • SDM moved office from South Melbourne to South Yarra (what is it about the south?)
  • I finished Guitar Hero 3 on Easy, Medium and on Coop Medium (Started on hard but my hand cramped)
  • Thanks to Christmas I increased my Xbox Game Collection substantially
  • I managed to save all limbs and both eyebrows despite my home made explosives on New Years eve.
  • Trekked over to Adelaide for the SDM Away days
  • Had my MVP status renewed for another year
  • Successfully registered for the MVP Summit 2008 (Seattle here I come!)
  • MOSSIG had the first meeting for 2008

While that’s the main stuff that comes to mind, there was more, but not too much worth mentioning. My Chinese new years resolution is to post more regularly and first order of business is to get some useful posts up here so stay tuned!

Finally I should let you know the next MOSSIG meeting is coming up in a little over 2 weeks on the 27th of Feb this should be a great night, We have Tim Wragg, Chris O’Connor and Myself all presenting so come along an have some food and a chat and check out the content. I’ll get a locked down agenda up in the next day or so