We are now ready to make our WeightTracker application do something useful.

That something useful is composed of two stories:

  • The user enters a weight, and it’s stored to the user’s HealthVault record
  • The weight measurements in the user’s record are displayed

We’ll do them in order.

Entering and storing a weight

Looking at default.aspx, you will find that it’s prepopulated with some controls that we’ll be using in the tutorial. Some of the ones that we don’t need yet are marked as invisible. For now, just pretend that the ones that aren’t visible aren’t there, and nobody will get hurt.

For this story, we’ll be using the c_textboxWeight for the user to enter the weight, and the c_buttonSave for the user to press to save the weight.

Switching to the code file (Default.aspx.cs), we see that there’s a click handler c_buttonSave_Click() where we’ll write the code to save the weight value to the user’s record.

First, we’ll get the weight value that the user entered and convert it to an integer:

int weightInPounds = Int32.Parse(c_textboxWeight.Text);

Then we’ll create an instance of the Weight type, which is (surprise) the type you use to store weights.

Weight weight = new Weight();

Now, we need to put the weight value from the user into the weight instance. But we have a problem.

To make weight values interchangeable between applications, the Weight data type stores weight values measured in kilograms. But most users in the US would prefer to see their weight displayed in pounds.

To fix this, we could just tell applications to perform the appropriate conversions to and from whatever unit they want to use, but that may cause problems with round-trip conversions:

3 miles -> 4828.031 meters

4828.031 meters –> 2.99999938 miles

HealthVault solves the problem by storing measurements in two separate formats – the exact way the user entered the value, and the value stored in the standard units. The first one is used when an application needs to display a value, and the second one is used to perform calculations.

Back to our code. We’ll start by storing the weight using our standard measure:

weight.Value.Kilograms = weightInPounds / 2.204;

And then we’ll set what we call the DisplayValue, which is the value the user entered.

weight.Value.DisplayValue = new DisplayValue(weightInPounds, "pounds");

Now that we’ve stored the value in the weight instance, we need to save it to the appropriate HealthVault record. We do that with the following code:

PersonInfo.SelectedRecord.NewItem(weight);

HealthVault organizes data into records, where each record holds data for a specific person. Data access is always performed through a specific person’s login. So…

PersonInfo corresponds to the person who is currently logged in. When they chose to authorize an application, they selected a specific record to authorize, and that is returned to the application in SelectedRecord. So PersonInfo.SelectedRecord is shorthand for “the record the user chose”.

It is possible for the application to redirect to the HealthVault shell to switch to a different record, or for an application to deal with more than one record at the same time, but that’s beyond what we’re trying to do right now.

Querying and displaying weights

Now that we’ve figured out how to save weights, we need to write some code that will fetch the weights that we’ve entered and display them in a table. We’ll put that code in the Page_Prerender() method.

<aside>

We use Page_Prerender rather than Page_Load because any events – such as the one fired when the user enters a new weight – occur after Page_Load but before Page_Prerender. So, if we put our code in Page_Load, newly entered weights would not show up.

</aside>

First, we need a way to query the current record. This is done through the HealthRecordSearcher class, which we can get from the selected record:

HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher();

Next, we need a way to specify which items we want to read from the record. That is done using the HealthRecordFilter class. It has a number of options that can be used to control what items it returns – we will use it in the simplest way by specifying the type that we want returned:

 

HealthRecordFilter filter = new HealthRecordFilter(Weight.TypeId);
searcher.Filters.Add(filter);

 

Now we want to send that request over to the HealthVault server, and get the weight items back:

 

HealthRecordItemCollection weights = searcher.GetMatchingItems()[0];

 

<aside>

You may have noticed that HealthRecordSearcher.Filters is a collection of filters rather than a single filter. If you want to do more than one query in a single request, you can add multiple filters to the searcher object, and they will all get executed in one batch.

When you call GetMatchingItems(), you get a collection of result collections, with one result collection for each filter. Since there’s only one filter here, we look at the first collection only.

Executing multiple filters at once may improve the performance of querying.

</aside>

Finally, we need to walk through the returned weight items and display them. We do that with the following code (including some canned code to do the ASP.NET table manipulation):

AddHeaderCells(c_tableWeight, "Date", "Weight");
foreach (Weight weight in weights)
{
    AddCellsToTable(c_tableWeight, weight.When.ToString(), 
                             weight.Value.DisplayValue.ToString());
}

The two helper methods make adding items to the table a little easier. Note that we are using the weight DisplayValue to show to the user.

Next Time

In the next episode, we’ll add some calculations to our application…

#5