Windows Phone – Current weather application

When I am “jogging” around some programming forums, I found out an interesting website http://www.webservicex.net/WCF/default.aspx which provides us many web services in many fields which can be used in our application. As you can see in URL, the web services of this site may be based on WCF which has a many advantages in compare to normal web service. Therefore I would like to use this free web service to write a small application telling me the current weather of a specific city. This application should work in portrait and landscape mode as images below.

So that the application is compatible in 2 modes, I used ScrollViewer and StackPanel to store the controls and let them automatically adjust when changing between 2 modes.

<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
	<StackPanel Orientation="Vertical">
		<StackPanel Orientation="Vertical">
			<StackPanel  Orientation="Horizontal" Width="450">
				<TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" Name="textBlock1" Text="Country" Width="74" />
				<swci:AutoCompleteBox GotFocus="acbCountry_GotFocus" LostFocus="acbCountry_LostFocus"  x:Name="acbCountry" HorizontalAlignment="Left" Width="199"></swci:AutoCompleteBox>
				<Button Content="Set Default" Height="72" HorizontalAlignment="Left"  Name="btnSetAsDefault" VerticalAlignment="Top" Width="183" Click="btnSetAsDefault_Click" />
			</StackPanel>
			<StackPanel Orientation="Horizontal" Width="449">
				<TextBlock HorizontalAlignment="Left" Name="textBlock2" Text="City" VerticalAlignment="Center" Width="74" />
				<swci:AutoCompleteBox x:Name="acbCity"  HorizontalAlignment="Left" Width="199"></swci:AutoCompleteBox>
				<Button Content="Browse" Height="72" HorizontalAlignment="Left"  Name="btnBrowse" VerticalAlignment="Top" Width="183" Click="btnBrowse_Click" />
			</StackPanel>
		</StackPanel>
		<Rectangle Height="25"></Rectangle>
		<StackPanel Orientation="Vertical" Width="450">
			<StackPanel Orientation="Vertical">
				<TextBlock FontSize="20" Text="{Binding Location}" HorizontalAlignment="Left" Name="textBlock10"  VerticalAlignment="Top" />
				<TextBlock FontSize="14" Text="{Binding Time}" HorizontalAlignment="Left" Name="textBlock11" VerticalAlignment="Top" />
			</StackPanel>
			<Rectangle Height="25"></Rectangle>
			<StackPanel Orientation="Horizontal">
				<StackPanel Orientation="Vertical">
					<Image Source="{Binding SkyConditionImage}"></Image>
					<TextBlock Text="{Binding SkyConditions}" HorizontalAlignment="Left" Name="textBlock5"  VerticalAlignment="Top" />
				</StackPanel>
				<Rectangle Width="25"></Rectangle>
				<StackPanel Orientation="Vertical">
					<TextBlock FontSize="48" Text="{Binding Temperature}" HorizontalAlignment="Left" Name="textBlock6"  VerticalAlignment="Top" />

					<Rectangle Height="15"></Rectangle>
					<TextBlock Width="270" TextWrapping="Wrap" Text="{Binding Wind}"  HorizontalAlignment="Left"  Name="textBlock3" VerticalAlignment="Top" />

					<Rectangle Height="15"></Rectangle>
					<TextBlock Height="30" Text="{Binding RelativeHumidity}" HorizontalAlignment="Left"  Name="textBlock8" VerticalAlignment="Top" />

					<Rectangle Height="15"></Rectangle>
					<TextBlock Height="30" Text="{Binding DewPoint}" HorizontalAlignment="Left"  Name="textBlock7"  VerticalAlignment="Top" />

					<Rectangle Height="15"></Rectangle>
					<TextBlock Height="30" Text="{Binding Pressure}" HorizontalAlignment="Left"  Name="textBlock9" VerticalAlignment="Top" />

					<Rectangle Height="15"></Rectangle>
					<TextBlock Height="30" Text="{Binding VisibilityW}" HorizontalAlignment="Left"  Name="textBlock4"  VerticalAlignment="Top" />
				</StackPanel>
			</StackPanel>
		</StackPanel>
	</StackPanel>
</ScrollViewer>

You can see that I used AutoCompleteBox instead of ComboBox because the list of countries and cities are too long. If I use the ComboBox, the drop down list will exceed the height of screen and I must scroll down to choose which will surely lead the phone to crash. I think cause of this reason ComboBox is not officially supported in Windows Phone although we can use it by adding it directly in XAML file. In this version, only countries below are supported

public List<string> Countries
{
	get
	{
		string[] aCountries = {
		"Afghanistan","Algeria","Angola","Argentina","Armenia","Australia","Austria","Azerbaijan","Belarus","Belgium","Benin",
		"Bolivia","Botswana","Brazil","Bulgaria","Burundi","Canada","Central African Republic","Chad","Chile","China",
		"Colombia","Congo","Costa Rica","Cote d'Ivoire","Croatia","Czech Republic","Denmark","Djibouti","Dominican Republic","DRC",
		"Ecuador","Egypt","El Salvador","Estonia","Ethiopia","Finland","France","Gabon","Gambia","Germany",
		"Ghana","Greece","Guatemala","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Ireland",
		"Israel","Italy","Japan","Jordan","Kazakhstan","Kenya","Korea","Kyrgyzstan","Latvia","Lebanon",
		"Lesotho","Lithuania","Macao","Madagascar","Malawi","Malaysia","Mali","Mauritius","Mexico","Moldova",
		"Morocco","Mozambique","Namibia","Netherlands","New Zealand","Nigeria","Norway","Oman","Pakistan","Panama",
		"Paraguay","Peru","Philippines","Poland","Portugal","Puerto Rico","Romania","Russia, CIS and Baltics","Rwanda","Sao Tome and Principe",
		"Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","Spain",
		"Sweden","Switzerland","Taiwan","Tajikistan","Tanzania","Thailand","Togo","Tunisia","Turkey","Turkmenistan",
		"Uganda","Ukraine","United Arab Emirates","United Kingdom","United States","Uruguay","Uzbekistan","Venezuela","Viet Nam","Zambia",
		"Zimbabwe"
		};
		List<string> lstResult = new List<string>();
		lstResult.AddRange(aCountries);
		return lstResult;
	}
}

When a user enters a country name, the application will connect to web service and get supported cities of that country and fill this list to the second AutoCompleteBox.

public void GetAvailableCities(string CountryName)
{
	this.CountryName = CountryName;
	m_gwscClient.GetCitiesByCountryCompleted += new EventHandler<GlobalWeatherService.GetCitiesByCountryCompletedEventArgs>(gwscClient_GetCitiesByCountryCompleted);
	m_gwscClient.GetCitiesByCountryAsync(CountryName);
}

void gwscClient_GetCitiesByCountryCompleted(object sender, GlobalWeatherService.GetCitiesByCountryCompletedEventArgs e)
{
	XDocument doc = XDocument.Parse(e.Result);
	AvailableCities = new List<string>();
	doc.Descendants("City").ToList().ForEach(x => AvailableCities.Add(x.Value));
	if (GetCitiesByCountryCompleted != null) GetCitiesByCountryCompleted(this, new EventArgs());
}

Because I can only get cities list asynchronously, I add an event to notify the View when the progress finishes and load this list to AutoCompleteBox. After choosing appropriate location, the user gets weather info through clicking button “Browse”. Another asynchronous call to web service will be executed to fetch weather data and fill the information into controls.

void m_gwscClient_GetWeatherCompleted(object sender, GlobalWeatherService.GetWeatherCompletedEventArgs e)
{
	if (e.Result != "Data Not Found")
	{
		XDocument doc = XDocument.Parse(e.Result);

		Location = doc.Descendants("Location").ToList()[0].Value;
		NotifyPropertyChanged("Location");

		Time = doc.Descendants("Time").ToList()[0].Value;
		NotifyPropertyChanged("Time");

		Wind = "Wind: " + doc.Descendants("Wind").ToList()[0].Value;
		NotifyPropertyChanged("Wind");

		VisibilityW = "Visibility: " + doc.Descendants("Visibility").ToList()[0].Value;
		NotifyPropertyChanged("VisibilityW");

		if (doc.Descendants("SkyConditions").ToList().Count > 0)
			SkyConditions = doc.Descendants("SkyConditions").ToList()[0].Value;
		NotifyPropertyChanged("SkyConditions");

		string strUrl = "";
		switch (SkyConditions.Trim())
		{
			case "mostly cloudy":
				strUrl = "Images/mostlycloudy.png";
				break;
			case "partly cloudy":
				strUrl = "Images/partlycloudy.png";
				break;
			case "mostly clear":
				strUrl = "Images/partlycloudy.png";
				break;
			default:
				break;
		}
		SkyConditionImage = new BitmapImage(new Uri(strUrl, UriKind.Relative));
		NotifyPropertyChanged("SkyConditionImage");

		Temperature = doc.Descendants("Temperature").ToList()[0].Value;
		NotifyPropertyChanged("Temperature");

		DewPoint = "Dew Point: " + doc.Descendants("DewPoint").ToList()[0].Value;
		NotifyPropertyChanged("DewPoint");

		RelativeHumidity = "Relative Humidity: " + doc.Descendants("RelativeHumidity").ToList()[0].Value;
		NotifyPropertyChanged("RelativeHumidity");

		Pressure = "Pressure: " + doc.Descendants("Pressure").ToList()[0].Value;
		NotifyPropertyChanged("Pressure");

		Status = doc.Descendants("Status").ToList()[0].Value;
		NotifyPropertyChanged("Status");
	}
	else
	{
		Location = "N/A";
		NotifyPropertyChanged("Location");

		Time = "N/A";
		NotifyPropertyChanged("Time");

		Wind = "Wind: " + "N/A";
		NotifyPropertyChanged("Wind");

		VisibilityW = "Visibility: " + "N/A";
		NotifyPropertyChanged("VisibilityW");

		SkyConditions = "N/A";
		NotifyPropertyChanged("SkyConditions");

		Temperature = "N/A";
		NotifyPropertyChanged("Temperature");

		DewPoint = "Dew Point: " + "N/A";
		NotifyPropertyChanged("DewPoint");

		RelativeHumidity = "Relative Humidity: " + "N/A";
		NotifyPropertyChanged("RelativeHumidity");

		Pressure = "Pressure: " + "N/A";
		NotifyPropertyChanged("Pressure");

		Status = "N/A";
		NotifyPropertyChanged("Status");
	}
}

The application can be upgraded by adding forecast feature. I will add it later if I have time. The code is quick and dirty because I just want to play around with web service and UI components and spend time to make a working Facebook API for Windows Phone. The complete source code you can download here “Windows Phone Weather

One thought on “Windows Phone – Current weather application”

Leave a Reply

Your email address will not be published. Required fields are marked *