Quickstart: Read data from a service (XAML)
[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]
By using the Hub, Grid, or Split project template in Visual Studio, you can more effectively create an app that displays data from any service, database, or other data source. These templates share a data model that organizes information into Items and groups, and you can more easily add functionality to your app if you organize your data to follow that model.
This topic demonstrates how to create a sample app that's based on the Hub project template. The sample app shows real-time property values from a service that you can subscribe to in the Microsoft Azure Marketplace. You can also apply most of the data concepts in this topic to projects that are based on the Grid or Split template, and that use other kinds of data sources.
For clarity, this topic shows only the code or markup that highlights key points, but you can find the following complete samples in the MSDN Code Gallery:
Sample | Description |
---|---|
Universal Windows app that consumes data from the Azure Marketplace | Uses a universal app project template to target Windows desktops and tablets as well as Windows 8.1 devices. This sample provides the C# version of the snippets that are featured in this topic. |
Portable class library that consumes data from the Azure Marketplace | Uses a portable class library to target Windows desktops and tablets as well as Windows 8.1 devices. This sample provides the Visual Basic version of the snippets that are featured in this topic. |
To see how you can use Windows Communication Foundation (WCF) Data Services Client library to show data in your app, see Hub template sample that consumes data from the Azure Marketplace (Windows 8.1). None of the code from that sample appears in this topic.
As you create this app, you'll perform the following tasks:
- Define your data.
- Show data in your pages as you design them.
- Get data from a service.
- Consume data in the hub page.
Define your data
First, figure out what kind of data you want to show and where you can get it. The sample uses data from the Microsoft Azure Marketplace. After you find a data source, decide how you want to organize that data.
In this section, you'll learn how to do the following:
- Find data.
- Organize your data into groups and items.
Find data
The sample uses data from the following services, which are available in the Microsoft Azure Marketplace:
Service | Description |
---|---|
PropertyDetailsAPI | Provides data about a property, such as its estimated value, taxes, and the number of bedrooms and bathrooms it has. |
NeighborhoodDetailsAPI | Provides statistical data about the city in which the property is located, such as average tax rates, average home values, and percentage of flips. |
Bing Search API | Provides search results. The sample uses this service only to obtain an image of the city the property is located in. |
To use these services, you'll have to subscribe to them, and then you'll receive a key. Place that key in the code that you write to return results.
Organize your data into groups and items
The sample organizes the information that it retrieves from services into the following groups:
Group | Items |
---|---|
Primary house | primary house |
Comparable houses | comparable house # 1 comparable house # 2 comparable house # 3 comparable house # 4 comparable house # 5 comparable house # 6 |
The first group is named Primary house and contains only one item: the house that the user wants more information about. The group holds only one item because of the design of the page. Data sources might enforce how data is organized, but you can organize your groups and items however you want.
In the Comparable houses group, each item (for example, comparable house #1) contains several fields, such as Street, ZipCode, YearBuilt, and ImagePath. For a complete list of fields, see the sample.
Show data in your pages as you design them
To view sample data in your designer as you customize the layout of your pages, perform these tasks:
- Add fields to the sample data classes.
- Add sample data.
- Bind controls in the page to sample data.
Add fields to the sample data classes
The data model contains a group class and an item class, and you can add your fields to those classes.
To find the group and item classes, open Solution Explorer, and then expand the Data Model node of your project. The group and item classes are in the SampleDataSource.cs or SampleDataSource.vb file.
The following code shows the group and item classes in the sample.
public class SampleDataGroup
{
public SampleDataGroup(String uniqueId, String title)
{
this.UniqueId = uniqueId;
this.Title = title;
this.Items = new ObservableCollection<SampleDataItem>();
}
}
public class SampleDataItem
{
public SampleDataItem(String uniqueId, String title, String imagePath, String street, String zipcode, String city,
String state, String taxassessment, String yearbuilt, String lotsizesqft,
String finishedsqft, String bathrooms, String bedrooms, String lastsolddate, String lastsoldprice,
String zestimateamount, String zestimatevaluechange, String zestimatevaluechangeduration,
String chartMedianCondoValue, String chartMedianHomeValue, String chartDollarsPSquareFt,
String chartZillowHomeValueIndex, String chartHomeType, String chartOwnRent,
String chartHomeSize, String chartYearBuilt, string neighborhoodImage)
{
this.UniqueId = uniqueId;
this.Title = title;
this.ImagePath = imagePath;
this.Street = street;
this.ZipCode = zipcode;
this.City = city;
this.State = state;
this.TaxAssessment = taxassessment;
this.YearBuilt = yearbuilt;
this.LotSizeSqFt = lotsizesqft;
this.FinishedSqFt = finishedsqft;
this.Bathrooms = bathrooms;
this.Bedrooms = bedrooms;
this.LastSoldDate = lastsolddate;
this.LastSoldPrice = lastsoldprice;
this.ZestimateAmount = zestimateamount;
this.ZestimateValueChange = zestimatevaluechange;
this.ZestimateValueChangeDuration = zestimatevaluechangeduration;
this.ChartMedianCondoValue = chartMedianCondoValue;
this.ChartMedianHomeValue = chartMedianHomeValue;
this.ChartDollarsPSquareFt = chartDollarsPSquareFt;
this.ChartZillowHomeValueIndex = chartZillowHomeValueIndex;
this.ChartHomeType = chartHomeType;
this.ChartOwnRent = chartOwnRent;
this.ChartHomeSize = chartHomeSize;
this.ChartYearBuilt = chartYearBuilt;
this.NeighborhoodImage = neighborhoodImage;
}
Public Class SampleDataGroup
Private Shared _baseUri As New Uri("ms-appx:///")
Public Sub New(uniqueId As String, title As String)
Me.UniqueId = uniqueId
Me.Title = title
Me.Items = New ObservableCollection(Of SampleDataItem)()
End Sub
End Class
Public Class SampleDataItem
Private Shared _baseUri As New Uri("ms-appx:///")
Public Sub New(uniqueId As String, title As String, imagePath As String, street As String, zipcode As String, _
city As String, state As String, taxassessment As String, yearbuilt As String, lotsizesqft As String, _
finishedsqft As String, bathrooms As String, bedrooms As String, lastsolddate As String, _
lastsoldprice As String, zestimateamount As String, zestimatevaluechange As String, _
zestimatevaluechangeduration As String, chartMedianCondoValue As String, chartMedianHomeValue As String, _
chartDollarsPSquareFt As String, chartZillowHomeValueIndex As String, chartHomeType As String, _
chartOwnRent As String, chartHomeSize As String, chartYearBuilt As String, neighborhoodImage As String)
Me.UniqueId = uniqueId
Me.Title = title
Me.ImagePath = imagePath
Me.Street = street
Me.ZipCode = zipcode
Me.City = city
Me.State = state
Me.TaxAssessment = taxassessment
Me.YearBuilt = yearbuilt
Me.LotSizeSqFt = lotsizesqft
Me.FinishedSqFt = finishedsqft
Me.Bathrooms = bathrooms
Me.Bedrooms = bedrooms
Me.LastSoldDate = lastsolddate
Me.LastSoldPrice = lastsoldprice
Me.ZestimateAmount = zestimateamount
Me.ZestimateValueChange = zestimatevaluechange
Me.ZestimateValueChangeDuration = zestimatevaluechangeduration
Me.ChartMedianCondoValue = chartMedianCondoValue
Me.ChartMedianHomeValue = chartMedianHomeValue
Me.ChartDollarsPSquareFt = chartDollarsPSquareFt
Me.ChartZillowHomeValueIndex = chartZillowHomeValueIndex
Me.ChartHomeType = chartHomeType
Me.ChartOwnRent = chartOwnRent
Me.ChartHomeSize = chartHomeSize
Me.ChartYearBuilt = chartYearBuilt
Me.NeighborhoodImage = neighborhoodImage
End Sub
End Class
Add sample data
As you design pages, add the data that you want your designer to display. The Hub project template contains a file that already has sample data in it. That file is named SampleData.json, and you can find it in the Data Model node of your project.
To show your data, modify SampleData.json. The following example shows sample data for only one group and one item in that group. This example doesn't show the entire sample data file.
{"Groups":[
{
"UniqueId": "houseItems",
"Title": "Your Selected Home",
"Items":
[
{
"UniqueId": "houseOfInterest",
"Title": "Your Selected Home",
"ImagePath": "Assets/PhotoNotAvailable.jpg",
"Street" : "4567 Main St",
"ZipCode" : "98052",
"City" : "Buffalo",
"State" : "NY",
"TaxAssessment" : "288500.0",
"YearBuilt" : "2007",
"LotSizeSqFt" : "6969",
"FinishedSqFt" : "2530",
"Bathrooms" : "3.0",
"Bedrooms" : "3",
"LastSoldDate" : "10/11/2007",
"LastSoldPrice" : "444000",
"ZestimateAmount" : "$391,357",
"ZestimateValueChange" : "13977",
"ZestimateValueChangeDuration" : "30",
"ChartMedianCondoValue" : "http://www.zillow.com/app?chartType=affordability_avgCondoValue&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartMedianHomeValue" : "http://www.zillow.com/app?chartType=affordability_avgHomeValue&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartDollarsPSquareFt" : "http://www.zillow.com/app?chartType=affordability_pricePerSqft&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartZillowHomeValueIndex" : "http://www.zillow.com/app?chartType=affordability_ZindexByDistribution&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartHomeType" : "http://www.zillow.com/app?chartType=home_homeType&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartOwnRent" : "http://www.zillow.com/app?chartType=home_ownVsRent&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartHomeSize" : "http://www.zillow.com/app?chartType=home_homeSize&graphType=barChart®ionId=17222®ionType=6&service=chart",
"ChartYearBuilt" : "http://www.zillow.com/app?chartType=home_yearBuilt&graphType=barChart®ionId=17222®ionType=6&service=chart",
"NeighborhoodImage" : "http://www.hanifworld.com/Buffalo/15-Downtown%20Buffalo-New%20York.JPG"
}
]
},
Bind controls in the page to sample data
Each hub section in your HubPage.xaml file contains a reference to your sample data file. For example, the first hub section of the sample contains the following set of attribute values:
d:DataContext="{Binding Groups[0], Source={d:DesignData Source=/DataModel/SampleData.json,
Type=data:SampleDataSource}}"
The d:DataContext
property is the design-time data context. This property specifies the data that will appear in your designer as you modify pages. The property contains three attributes .
Attribute | Purpose |
---|---|
Type | The name of the type in your project that contains the property that you'll refer to in the Binding attribute. In the sample, the name of the type is SampleDataSource . The name of the group is Groups . Notice the prefix data: in front of the term SampleDataSource . This prefix is an XML namespace that's defined as follows at the top of the XAML file for the hub page: xmlns:data="using:ZillowHub.Data ". The prefix data: is just a short way to refer to that namespace. |
Binding | The property you'd like to bind to. This example binds to the first group in the Groups collection. |
Source | A reference to the sample data file. |
To show data in your hub page, bind the Text
property of any field to a corresponding field in your sample data file. For example, the Text
property of the following field is bound to the City
field of the first item in the group.
<TextBlock Style="{StaticResource SubheaderTextBlockStyle}" Grid.Row="0" Grid.Column="0"
Margin="0,10,0,0" TextWrapping ="Wrap" Text="{Binding Items[0].City, Mode=OneWay}" />
Remember that the group in context is the group to which you bound the entire hub section in the previous example.
Get data from a service
So far, you've configured the project to show sample data in your designer. This configuration helps you design your pages and lays some of the groundwork for the steps that follow. However, you'll want users to view live data when they run your app. To enable this functionality, follow these steps:
- Query a service.
- Populate groups and items.
- Enable the hub page to consume groups of data.
Query a service
Services in the Microsoft Azure Marketplace return information as OData feeds. The easiest way for your app to consume an OData feed is to use an HttpWebRequest object. The following example uses an HTTPWebRequest object to request data from a service, and then obtains a response object that contains a JSON-formatted response.
private async Task<dynamic> getDataFromService(string queryString)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(queryString);
request.Credentials = new NetworkCredential("<Your account key goes here>",
"<Your account key goes here>");
var response = await request.GetResponseAsync().ConfigureAwait(false);
var stream = response.GetResponseStream();
var streamReader = new StreamReader(stream);
string responseText = streamReader.ReadToEnd();
dynamic data = JsonConvert.DeserializeObject(responseText);
return data;
}
catch (Exception)
{
return null;
}
}
Private Async Function getDataFromService(queryString As String) As Task(Of JObject)
Try
Dim request As HttpWebRequest = DirectCast(WebRequest.Create(queryString), HttpWebRequest)
request.Credentials = New NetworkCredential("<Your account key goes here>",
"<Your account key goes here>")
Dim response = Await request.GetResponseAsync().ConfigureAwait(False)
Dim stream = response.GetResponseStream()
Dim streamReader = New StreamReader(stream)
Dim responseText As String = streamReader.ReadToEnd()
Dim data As JObject = JsonConvert.DeserializeObject(responseText)
Return data
Catch generatedExceptionName As Exception
Return Nothing
End Try
End Function
Populate groups and items
This example performs the following tasks to organize data into groups and items:
- Gets service data.
- Populates an item object by using data from the service response.
- Adds the item to a group, and then returns that group to the caller.
public async Task<SampleDataGroup> GetHouse(string address, string cityStateZip)
{
// Get house.
string queryString =
"https://api.datamarket.azure.com/data.ashx/Zillow/PropertyDetailsAPIs/v1/GetDeepSearchResults?" +
"Address='" + address + "'&CityStateAndZipCode='" + cityStateZip +
"'&$format=json";
dynamic results = await getDataFromService(queryString).ConfigureAwait(false);
if (results == null)
{
return null;
}
dynamic house = results["d"]["results"][0];
SampleDataGroup myGroup = new SampleDataGroup("house", "");
SampleDataItem item = new SampleDataItem((string)house["ZillowPropertyId"],
"", "Assets/PhotoNotAvailable.jpg",
(string)house["Street"],
(string)house["ZipCode"],
(string)house["City"],
(string)house["State"],
(string)house["TaxAssessment"],
(string)house["YearBuilt"],
(string)house["LotSizeSqFt"],
(string)house["FinishedSqFt"],
(string)house["Bathrooms"],
(string)house["Bedrooms"],
(string)house["LastSoldDate"],
(string)house["LastSoldPrice"],
(string)house["ZestimateAmount"],
(string)house["ZestimateValueChange"],
(string)house["ZestimateValueChangeDuration"],
"",
"",
"",
"",
"",
"",
"",
"",
"");
// get an image of the house.
queryString =
"https://api.datamarket.azure.com/data.ashx/Zillow/PropertyDetailsAPIs/v1/GetUpdatedPropertyDetails?" +
"ZillowPropertyID=" + house["ZillowPropertyId"] + "&$format=json";
results = await getDataFromService(queryString).ConfigureAwait(false);
if (results != null)
{
dynamic houseImage = results["d"]["results"][0];
item.ImagePath = (string)houseImage["ImageUrl"];
}
else
{
item.ImagePath = "Assets/PhotoNotAvailable.jpg";
}
// get demographic data for the city.
queryString =
"https://api.datamarket.azure.com/data.ashx/Zillow/NeighborhoodDataAPIs/v1/GetDemographicsByCity?" +
"City='" + item.City + "'&State='" + item.State + "'&$format=json";
results = await getDataFromService(queryString).ConfigureAwait(false);
if (results != null)
{
dynamic demographics = results["d"]["results"];
item.ChartMedianCondoValue = (string)demographics[0]["ChartUrl"];
item.ChartMedianHomeValue = (string)demographics[1]["ChartUrl"];
item.ChartDollarsPSquareFt = (string)demographics[2]["ChartUrl"];
item.ChartZillowHomeValueIndex = (string)demographics[3]["ChartUrl"];
item.ChartHomeType = (string)demographics[4]["ChartUrl"];
item.ChartOwnRent = (string)demographics[5]["ChartUrl"];
item.ChartHomeSize = (string)demographics[6]["ChartUrl"];
item.ChartYearBuilt = (string)demographics[7]["ChartUrl"];
}
else
{
item.ChartMedianCondoValue = "None found";
item.ChartMedianHomeValue = "None found";
item.ChartDollarsPSquareFt = "None found";
item.ChartZillowHomeValueIndex = "None found";
item.ChartHomeType = "None found";
item.ChartOwnRent = "None found";
item.ChartHomeSize = "None found";
item.ChartYearBuilt = "None found";
}
// get image of the city.
queryString =
"https://api.datamarket.azure.com/Bing/Search/v1/Image?Query='" +
item.City + ", " + item.State + "'&$format=json";
results = await getDataFromService(queryString).ConfigureAwait(false);
if (results != null)
{
dynamic images = results["d"]["results"][0];
item.NeighborhoodImage = (string)images["MediaUrl"];
}
else
{
item.NeighborhoodImage = "Assets/PhotoNotAvailable.jpg";
}
myGroup.Items.Add(item);
return myGroup;
}
Public Async Function GetHouse(address As String, cityStateZip As String) As Task(Of SampleDataGroup)
' Get house.
Dim queryString As String = "https://api.datamarket.azure.com/data.ashx/Zillow/PropertyDetailsAPIs/v1/GetDeepSearchResults?" & "Address='" & address & "'&CityStateAndZipCode='" & cityStateZip & "'&$format=json"
Dim results As JObject = Await getDataFromService(queryString).ConfigureAwait(False)
If results Is Nothing Then
Return Nothing
End If
Dim house = results("d")("results")(0)
Dim myGroup As New SampleDataGroup("house", "")
Dim item As New SampleDataItem(house("ZillowPropertyId").ToString(), "", "Assets/PhotoNotAvailable.jpg", house("Street").ToString(), house("ZipCode").ToString(), house("City").ToString(), _
house("State").ToString(), house("TaxAssessment").ToString(), house("YearBuilt").ToString(), house("LotSizeSqFt").ToString(), house("FinishedSqFt").ToString(), house("Bathrooms").ToString(), _
house("Bedrooms").ToString(), house("LastSoldDate").ToString(), house("LastSoldPrice").ToString(), house("ZestimateAmount").ToString(), house("ZestimateValueChange").ToString(), house("ZestimateValueChangeDuration").ToString(), _
"", "", "", "", "", "", _
"", "", "")
' get an image of the house.
queryString = ("https://api.datamarket.azure.com/data.ashx/Zillow/PropertyDetailsAPIs/v1/GetUpdatedPropertyDetails?" & "ZillowPropertyID=") + house("ZillowPropertyId").ToString() & "&$format=json"
results = Await getDataFromService(queryString).ConfigureAwait(False)
If results IsNot Nothing Then
Dim houseImage = results("d")("results")(0)
item.ImagePath = houseImage("ImageUrl").ToString()
Else
item.ImagePath = "Assets/PhotoNotAvailable.jpg"
End If
' get demographic data for the city.
queryString = (("https://api.datamarket.azure.com/data.ashx/Zillow/NeighborhoodDataAPIs/v1/GetDemographicsByCity?" & "City='") + item.City & "'&State='") + item.State & "'&$format=json"
results = Await getDataFromService(queryString).ConfigureAwait(False)
If results IsNot Nothing Then
Dim demographics = results("d")("results")
item.ChartMedianCondoValue = demographics(0)("ChartUrl").ToString()
item.ChartMedianHomeValue = demographics(1)("ChartUrl").ToString()
item.ChartDollarsPSquareFt = demographics(2)("ChartUrl").ToString()
item.ChartZillowHomeValueIndex = demographics(3)("ChartUrl").ToString()
item.ChartHomeType = demographics(4)("ChartUrl").ToString()
item.ChartOwnRent = demographics(5)("ChartUrl").ToString()
item.ChartHomeSize = demographics(6)("ChartUrl").ToString()
item.ChartYearBuilt = demographics(7)("ChartUrl").ToString()
Else
item.ChartMedianCondoValue = "None found"
item.ChartMedianHomeValue = "None found"
item.ChartDollarsPSquareFt = "None found"
item.ChartZillowHomeValueIndex = "None found"
item.ChartHomeType = "None found"
item.ChartOwnRent = "None found"
item.ChartHomeSize = "None found"
item.ChartYearBuilt = "None found"
End If
' get image of the city.
queryString = ("https://api.datamarket.azure.com/Bing/Search/v1/Image?Query='" + item.City & ", ") + item.State & "'&$format=json"
results = Await getDataFromService(queryString).ConfigureAwait(False)
If results IsNot Nothing Then
Dim images = results("d")("results")(0)
item.NeighborhoodImage = images("MediaUrl").ToString()
Else
item.NeighborhoodImage = "Assets/PhotoNotAvailable.jpg"
End If
myGroup.Items.Add(item)
Return myGroup
End Function
Enable the hub page to consume groups of data
The SampleDataSource file of your project already contains a method named GetGroupsAsync that returns groups of data to the hub page of your project. The following example modifies the GetGroupsAsync method.
public static async Task<IEnumerable<SampleDataGroup>> GetGroupsAsync(string address, string cityStateZip)
{
// if you are returning from an item details page, then there should already be groups in the collection.
if (address == "")
{
return _sampleDataSource.Groups;
}
_sampleDataSource.Groups.Clear();
var houseGroup = await _sampleDataSource.GetHouse(address, cityStateZip).ConfigureAwait(false);
if (houseGroup != null)
{
_sampleDataSource.Groups.Add(houseGroup);
}
// If no house is found, then there is no need to look for comparable houses and demographics.
if (_sampleDataSource.Groups.Count != 0)
{
var comparableGroup = await _sampleDataSource.GetComparableHouses(_sampleDataSource.Groups[0].Items[0].UniqueId).ConfigureAwait(false);
if (comparableGroup != null)
{
_sampleDataSource.Groups.Add(comparableGroup);
}
}
return _sampleDataSource.Groups;
}
Public Shared Async Function GetGroupsAsync(address As String, cityStateZip As String) As Task(Of IEnumerable(Of SampleDataGroup))
' if you are returning from an item details page, then there should already be groups in the collection.
If address = "" Then
Return _sampleDataSource.Groups
End If
_sampleDataSource.Groups.Clear()
Dim houseGroup = Await _sampleDataSource.GetHouse(address, cityStateZip).ConfigureAwait(False)
If houseGroup IsNot Nothing Then
_sampleDataSource.Groups.Add(houseGroup)
End If
' If no house is found, then there is no need to look for comparable houses and demographics.
If _sampleDataSource.Groups.Count <> 0 Then
Dim comparableGroup = Await _sampleDataSource.GetComparableHouses(_sampleDataSource.Groups(0).Items(0).UniqueId).ConfigureAwait(False)
If comparableGroup IsNot Nothing Then
_sampleDataSource.Groups.Add(comparableGroup)
End If
End If
Return _sampleDataSource.Groups
Return Nothing
End Function
Consume data in the hub page
Now you're ready to show data from groups and items in your hub page by associating groups of data with the default view model of that page. The default view model is basically a name/value pair that's associated with the page. See Navigation model (using C#/VB/C++ and XAML). You'll bind controls in your page to information that's associated with your default view model. In the sample app, users can also search for properties. In this section, you'll learn how to do the following:
- Enable users to search for a property.
- Populate the default view model.
- Populate the default view model whenever the page loads.
- Bind controls on the hub page to the view model.
Enable users to search for a property
You can add controls to an app bar so that users can search for information in the sample app. For general information about how to create and modify app bars, see Adding app bars. The following example adds two text boxes and a button to the app bar.
Note This example is from a Windows version of the hub page. See the samples described at the beginning of this topic to view a Windows Phone version.
<Page.BottomAppBar >
<AppBar x:Name="MyAppBar" IsOpen="true" IsSticky="True">
<Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<TextBlock x:Name="ErrorText" FontSize="16" Foreground="#FFFD0404" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20,0,0,0" />
<ProgressRing x:Name="Progress" FontSize="20" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Address: " VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="18" Margin="0,0,10,0" />
<TextBox x:Name="AddressTextBox" Grid.Row="1" Grid.Column="0" VerticalAlignment="Center" Width="400" HorizontalAlignment="Right" FontSize="20" />
<TextBlock Grid.Row="0" Grid.Column="1" Text="City, State or Zip: " VerticalAlignment="Center" HorizontalAlignment="Left" FontSize="18" Margin="10,0" />
<TextBox x:Name="CityStateZipTextBox" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" Width="250" HorizontalAlignment="Left" FontSize="20" Margin="10,0,0,0" />
<Button Grid.Row="1" Grid.Column="2" FontSize="20" Content="Search" Margin="10,0,0,0" Click="Button_Click"/>
</Grid>
</StackPanel>
</Grid>
</AppBar>
</Page.BottomAppBar>
Populate the default view model
The following example populates the default view model of the hub page when users search for a property. The code performs these actions:
- Passes the address and city, state, or zip code to the GetGroupsAsync method of your data model and returns a collection of groups.
- Associates the group that contains the house with a key that's named "houseItems".
- Associates the group that contains comparable houses with a key that's named "comparableHouseItems".
This example also caches search terms, manages user interface (UI) indicators, and performs other tasks.
Note This example is from a Windows version of the hub page. See the sample described at the beginning of this topic to view the Windows Phone version.
#region "Populate the view model by querying the data model"
private async void Button_Click(object sender, RoutedEventArgs e)
{
if (AddressTextBox.Text == "")
{
ErrorText.Text = "Please enter an address";
}
else if (CityStateZipTextBox.Text == "")
{
ErrorText.Text = "Please enter city and state or a zip code";
}
else
{
Windows.Storage.ApplicationDataContainer roamingSettings =
Windows.Storage.ApplicationData.Current.RoamingSettings;
roamingSettings.Values["address"] = AddressTextBox.Text;
roamingSettings.Values["cityStateZip"] = CityStateZipTextBox.Text;
pageTitle.Text = "Searching ...";
pageTitle.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
titleProgressRing.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
titleProgressRing.IsActive = true;
var groups = await SampleDataSource.GetGroupsAsync(AddressTextBox.Text, CityStateZipTextBox.Text);
if (groups.Count() > 0)
{
this.DefaultViewModel["houseItems"] = groups.ElementAt(0);
this.DefaultViewModel["comparableHouseItems"] = groups.ElementAt(1);
pageTitle.Text = "Real Estate Hub";
pageTitle.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
titleProgressRing.IsActive = false;
}
else
{
ErrorText.Text = "Please search for a property";
}
}
}
#endregion
#Region "Populate the view model by querying the data model"
Private Async Sub Button_Click(sender As Object, e As RoutedEventArgs)
If AddressTextBox.Text = "" Then
ErrorText.Text = "Please enter an address"
ElseIf CityStateZipTextBox.Text = "" Then
ErrorText.Text = "Please enter city and state or a zip code"
Else
' save parameters.
Dim roamingSettings As Windows.Storage.ApplicationDataContainer = Windows.Storage.ApplicationData.Current.RoamingSettings
roamingSettings.Values("address") = AddressTextBox.Text
roamingSettings.Values("cityStateZip") = CityStateZipTextBox.Text
pageTitle.Text = "Searching ..."
pageTitle.Foreground = New SolidColorBrush(Windows.UI.Colors.White)
titleProgressRing.Foreground = New SolidColorBrush(Windows.UI.Colors.White)
titleProgressRing.IsActive = True
Dim groups = Await SampleDataSource.GetGroupsAsync(AddressTextBox.Text, CityStateZipTextBox.Text)
If groups.Count > 0 Then
Me.DefaultViewModel("houseItems") = groups.ElementAt(0)
Me.DefaultViewModel("comparableHouseItems") = groups.ElementAt(1)
pageTitle.Text = "Real Estate Hub"
pageTitle.Foreground = New SolidColorBrush(Windows.UI.Colors.White)
titleProgressRing.IsActive = False
Else
ErrorText.Text = "Please search for a property"
End If
End If
End Sub
#End Region
Populate the default view model whenever the page loads
If a user chooses an item in the hub page, an items page appears. If you want data to appear in the hub page when users return to it, you must write code that restores the default view model. Because the groups and items in your data model maintain state between page views, you can reuse data in the groups and items that you've already populated. They're still in memory. The following example restores the values of the default view model by performing these actions:
- If the user is opening the page for the first time, finds cached search terms.
- If the user is opening the page by returning from an items page, calls the GetGroupsAsync method with empty search terms. That method returns groups and items that are already in memory.
- Associates the "houseItems" and "ComparableHouseItems" keys with the appropriate groups.
Note This example is from a Windows version of the hub page. See the sample described at the beginning of this topic to view the Windows Phone version.
#region "Populate page controls every time the page loads"
private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
string address = "";
string cityStateZip = "";
// First time page is loaded. See if we've saved the results of a previous search.
if (e.PageState == null)
{
Windows.Storage.ApplicationDataContainer roamingSettings =
Windows.Storage.ApplicationData.Current.RoamingSettings;
if (roamingSettings.Values.ContainsKey("address") &&
roamingSettings.Values.ContainsKey("cityStateZip"))
{
address = roamingSettings.Values["address"].ToString();
cityStateZip = roamingSettings.Values["cityStateZip"].ToString();
}
houseItemSection.Visibility = Visibility.Collapsed;
comparableSection.Visibility = Visibility.Collapsed;
demographicSection.Visibility = Visibility.Collapsed;
pageTitle.Text = "Loading Page...";
titleProgressRing.IsActive = true;
titleProgressRing.Foreground = new SolidColorBrush(Windows.UI.Colors.White);
ErrorText.Text = "";
Progress.IsActive = false;
}
var groups = await SampleDataSource.GetGroupsAsync(address, cityStateZip);
ErrorText.Text = "";
Progress.IsActive = false;
titleProgressRing.IsActive = false;
pageTitle.Text = "Real Estate Hub";
houseItemSection.Visibility = Visibility.Visible;
comparableSection.Visibility = Visibility.Visible;
demographicSection.Visibility = Visibility.Visible;
if (groups.Count() > 0)
{
this.DefaultViewModel["houseItems"] = groups.ElementAt(0);
this.DefaultViewModel["comparableHouseItems"] = groups.ElementAt(1);
}
else
{
ErrorText.Text = "Please search for a property";
}
}
#endregion
Private Async Sub NavigationHelper_LoadState(sender As Object, e As Common.LoadStateEventArgs)
Dim address As String = ""
Dim cityStateZip As String = ""
' First time page is loaded. See if we've saved the results of a previous search.
If e.PageState Is Nothing Then
Dim roamingSettings As Windows.Storage.ApplicationDataContainer = Windows.Storage.ApplicationData.Current.RoamingSettings
If roamingSettings.Values.ContainsKey("address") AndAlso roamingSettings.Values.ContainsKey("cityStateZip") Then
address = roamingSettings.Values("address").ToString()
cityStateZip = roamingSettings.Values("cityStateZip").ToString()
End If
houseItemSection.Visibility = Visibility.Collapsed
comparableSection.Visibility = Visibility.Collapsed
demographicSection.Visibility = Visibility.Collapsed
pageTitle.Text = "Loading Page..."
titleProgressRing.IsActive = True
titleProgressRing.Foreground = New SolidColorBrush(Windows.UI.Colors.White)
ErrorText.Text = ""
Progress.IsActive = False
End If
Dim groups = Await SampleDataSource.GetGroupsAsync(address, cityStateZip)
ErrorText.Text = ""
Progress.IsActive = False
titleProgressRing.IsActive = False
pageTitle.Text = "Real Estate Hub"
houseItemSection.Visibility = Visibility.Visible
comparableSection.Visibility = Visibility.Visible
demographicSection.Visibility = Visibility.Visible
If groups.Count > 0 Then
Me.DefaultViewModel("houseItems") = groups.ElementAt(0)
Me.DefaultViewModel("comparableHouseItems") = groups.ElementAt(1)
Else
ErrorText.Text = "Please search for a property"
End If
End Sub
Bind controls on the hub page to the view model
To show data in your hub page, you must set the data context of each section to a key in your default view model. For example, if you want a hub section to show data from the group that's associated with the "houseItems" key, set the DataContext attribute of your hub section as follows: DataContext="{Binding houseItems}
. In the sample, the entire section declaration appears like this:
<HubSection x:Name="houseItemSection" Width="500" x:Uid="houseItems"
Header="Featured House" IsHeaderInteractive="True"
DataContext="{Binding houseItems}" d:DataContext="{Binding Groups[0],
Source={d:DesignData Source=/DataModel/SampleData.json, Type=data:SampleDataSource}}">
You can bind the controls in the section to fields in the appropriate item of a group. In this case, you bind to fields in the first item in the "houseItems" group because that group contains only one item. For example, add the following XAML code to show the name of the city where the property is located: <TextBlock Text="{Binding Items[0].City >
.
Related topics
How to customize Visual Studio template data (XAML)
C#, VB, and C++ project templates
Universal Windows app that consumes data from the Azure Marketplace
Portable class library that consumes data from the Azure Marketplace
Hub template sample that consumes data from the Azure Marketplace (Windows 8.1)
Build apps that target Windows and Windows Phone by using Visual Studio