Reading Forms Data
I think we can read Forms data now.
We already added event handlers to two of our three combo-boxes (IdentitiesCombo, WorkspacesCombo), so let's do the same for the ToolsCombo, which contains a list of tools in the selected workspace. When the selection changes, we should read data from the tool.
private void ToolsCombo_SelectedIndexChanged(object sender, EventArgs e)
{
// Each item in the combobox is a ToolInfo, containing a Groove Tool
ToolInfo t = (ToolInfo)ToolsCombo.SelectedItem;
ReadDataFromTool(t.tool);
}
To display the data, let's drop a DataGridView into the form, and make it read-only. (DataGridView is new with Visual Studio 2005; if you're using Visual Studio 2003, a DataGrid is just as good). Then, when we have some data, let's assume we also have a DataSet. The only magic piece here is that the data set will need a particular name ("RecordDataSet"), because that's the name we'll receive from Groove.
private
void ReadDataFromTool(Tool t)
{
// Make a DataSet to contain the records
System.Data.
DataSet recordDataSet = new System.Data.DataSet("RecordDataSet");
// ... Get some data ...
// Bind the dataset to the grid view
dataGridView1.ReadOnly =
true;
dataGridView1.DataSource = recordDataSet.Tables[0];
}
Without further comment, let's just read data.
// The Tool has a web service URI for us to access its data via the GrooveForms service
string toolURI = t.Data;
GrooveForms formsService = new GrooveForms();
formsService.GrooveRequestHeaderValue =
new GrooveFormsWebService.GrooveRequestHeader();
formsService.GrooveRequestHeaderValue.GrooveRequestKey =
GWSUtil.GrooveLocalRequestKey;
formsService.GrooveRequestHeaderValue.GrooveIdentityURL = selectedIdentity.URI;
formsService.Url =
GWSUtil.GrooveURL + toolURI;
// Query for all the records, no attachments
GrooveFormsWebService.
RecordQuery recordQuery = new GrooveFormsWebService.RecordQuery();
recordQuery.FieldSchemaScopingElement =
"";
recordQuery.FieldSchemaScopingFlag =
"All";
recordQuery.FileAttachmentFormat =
"Base64";
recordQuery.FormURI =
"";
recordQuery.IncludeFileAttachmentContent =
false;
recordQuery.QueryMetadataOnly =
false;
recordQuery.UnreadRecordsOnly =
false;
recordQuery.ViewURI =
"";
recordQuery.WhereClause =
"";
// Ask service to query records
FormsRecordDataSet fds = formsService.QueryRecords(recordQuery);
And we end up with a FormsRecordDataSet, which is a serialized set of Groove Forms data retrieved from the web service. In this case we called QueryRecords(), which is a very flexible way to retrieve some or all records in a tool; it can include a WhereClause with some SQL-like syntax: a conditional expression or a series of conditional expressions joined by AND and OR logical operators (and parentheses), with the usual comparison operators, "LIKE" and "NOT LIKE". (The full documentation for this is in the API reference in the Groove Web Services GDK). To read a known subset of the data, an alternative to QueryRecords() would be ReadRecords(), which takes a list of record URIs for specific records.
The FormsRecordDataSet arrived in a SOAP packet as a chunk of XML, and it turns out that the XML format for this is designed to be essentially the same as a System.Data.DataSet serialization; there's an array of schema nodes, and an array of data nodes. So we can push that XML into our DataSet quite easily:
// If schema exists, load it into the DataSet
if (fds.Schema is System.Array)
{
// For Groove V3 it's safe to assume there is only one schema in the dataset (although this may change)
System.Xml.
XmlNode[] schemaNodes = (System.Xml.XmlNode[])fds.Schema;
foreach (System.Xml.XmlNode schemaNode in schemaNodes)
{
System.IO.
StringReader schemaReader = new System.IO.StringReader("<?xml version=\"1.0\"?>" + schemaNode.OuterXml);
recordDataSet.ReadXmlSchema(schemaReader);
}
}
// If data exists, load it into the DataSet
if (fds.Data is System.Array)
{
System.Xml.
XmlNode[] dataNodes = (System.Xml.XmlNode[])fds.Data;
foreach (System.Xml.XmlNode dataNode in dataNodes)
{
System.Xml.
XmlNodeReader dataReader = new System.Xml.XmlNodeReader(dataNode);
recordDataSet.ReadXml(dataReader, System.Data.
XmlReadMode.Auto);
}
}
And we're done! Because the FormsRecordDataSet includes its own schema, and the DataSet knows how to parse a schema in XML format, there's no need to wrestle with individual columns and their datatypes; it just drops right in. Then when bound to the DataGridView, we see Groove data in the form.
Copy, paste, build, run. Outlook shows my menu-button, and when I click the button, here's the form:
Wasn't that easy?