Windows Phone – Phone PC Connector through WCF service

Windows Phone OS is being developed and I do not know which protocol Microsoft use to allow users and developers to transfer data between PC and phone, may be USB, Wifi, Bluetooth, etc … Within these protocols I prefer using protocol based on IP therefore today I would like to write a small demonstration which lets me download/upload file from PC to phone/from phone to PC.
The Demo source code consists of 2 projects :
– The sever is a WPF application running on PC. When the server starts to run, a WCF service will be automatically executed and listens on specific port to request and gives response back to phone client.

– The client is a Silverlight application running on Windows Phone Emulator. The client requires information of the IP and opened port of server for building the connection and accessing the WCF service. These settings are stored in InsolatedStorageFile within AppSettings.xml file and can be edited by client.

Before I start to discuss a little about my demo, there are some requirements we should do so that it runs smoothly
– If you are running a firewall, you must register the server so that the firewall allows inbound and outbound traffic of server. This registration can be done with programming but I still don’t integrate it into program.


Server side

As I said above, the server will host a WCF service inside it and starts the service at the same time. This service will open an available port (which requires administrator right and access through firewall) and binds the service to that port.

void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
	try
	{
		lblServer.Content = TCPClass.GetIPV4();
		CustomConfiguration.Port = TCPClass.GetAvailablePort();
		txtPort.Content = CustomConfiguration.Port.ToString();
		txtServiceUri.Text = "http://" + TCPClass.GetIPV4() + ":" + CustomConfiguration.Port + CustomConfiguration.ServiceName;
		txtTargetFolder.Text = Directory.GetCurrentDirectory();
		m_wcfsFileTransfer = new WCFService();
		m_wcfsFileTransfer.CreateService();
	}
	catch (Exception ex)
	{
		MessageBox.Show(ex.Message);
	}
}

ServiceHost uses BasicHttpBinding with TransferMode set on Streamed. “Setting the transfer mode to Streamed enables streaming communication in both directions. Streamed transfers can improve the scalability of a service by eliminating the need for large memory buffers. Whether changing the transfer mode actually improves scalability in practice depends on the size of the messages being transferred. Improvements in scalability should be most evident when large messages use streamed instead of buffered transfers.“. I already set the buffer size very large (64 MB) for sending large file.

public void CreateService()
{
	try
	{
		Uri uriTcpAddress = new Uri("http://" + TCPClass.GetIPV4() + ":" + CustomConfiguration.Port + CustomConfiguration.ServiceName);
		Uri[] uriBaseAddress = { uriTcpAddress };

		m_shHost = new ServiceHost(typeof(FileStreamingService), uriBaseAddress);

		BasicHttpBinding ntbBind = new BasicHttpBinding(BasicHttpSecurityMode.None);
		ntbBind.MaxBufferPoolSize = (int)67108864;
		ntbBind.MaxBufferSize = (int)67108864;
		ntbBind.MaxReceivedMessageSize = (int)67108864;
		ntbBind.SendTimeout = TimeSpan.FromSeconds(15);
		ntbBind.MaxReceivedMessageSize = 67108864;
		ntbBind.ReaderQuotas.MaxArrayLength = 67108864;
		ntbBind.ReaderQuotas.MaxStringContentLength = 67108864;
		ntbBind.TransferMode = TransferMode.Streamed;

		m_shHost.AddServiceEndpoint(typeof(IFileStreaming), ntbBind, "");

		ServiceMetadataBehavior smbBehavior = m_shHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
		if (smbBehavior == null)
		{
			smbBehavior = new ServiceMetadataBehavior();
			smbBehavior.HttpGetEnabled = true;

			m_shHost.Description.Behaviors.Add(smbBehavior);
		}

		m_shHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "http://localhost:" + (CustomConfiguration.Port - 1).ToString() + CustomConfiguration.ServiceName + "/mex");
		m_shHost.Open();
	}
	catch (Exception ex)
	{
		throw ex;
	}
}

After creating service, we can defines some operation contract so that the client can access and transfer data.
– GetStream : download file from PC to phone.
– UploadStream : upload file from phone (IsolatedStorageFile) to PC.
– GetStartUpFolder : get the folder where the server program locates.
– GetFolderInfo : get list of files and sub-folders of a specific folder.

[ServiceContract]
public interface IFileStreaming
{
	[OperationContract]
	System.IO.Stream GetStream(string data);
	[OperationContract]
	bool UploadStream(FileUpload stream);
	[OperationContract]
	string GetStartUpFolder();
	[OperationContract]
	List<ObjectInfo> GetFolderInfo(string Folder);
}

Client side
The mission of client is pretty simple. It just calls the service with appropriate data and receives data back. The operations of WCF services will be parsed in class ViewModel and used in client to browse, upload, download file in PC and phone.

void Explorer_Loaded(object sender, RoutedEventArgs e)
{
	string strType = "";
	NavigationContext.QueryString.TryGetValue("Type", out strType);
	if (strType == "PCExplorer")
	{
		btnUp.Visibility = System.Windows.Visibility.Visible;
		tbCurrentFolder.Visibility = System.Windows.Visibility.Visible;
		m_bUpload = false;
		vm.ReadConfiguration();
		vm.StartPCExplorer();
	}
	else
	{
		btnUp.Visibility = System.Windows.Visibility.Collapsed;
		tbCurrentFolder.Visibility = System.Windows.Visibility.Collapsed;
		m_bUpload = true;
		vm.ReadConfiguration();
		vm.StartPhoneExplorer();
	}
}

What we should make a concern about is that the operations should be called asynchronously and the stream type will be therefore automatically converted to byte array.

public void StartPCExplorer()
{
	try
	{
		fscClient.GetStartUpFolderCompleted += new EventHandler<GetStartUpFolderCompletedEventArgs>(fscClient_GetStartUpFolderCompleted);
		fscClient.GetStartUpFolderAsync();
	}
	catch (Exception ex)
	{
		throw ex;
	}
}

I am installing VS 2010 on my desktop and therefore I can not develop Windows Phone Application on my desktop. I must use my laptop to develop client. Hence the project contains 2 separated solutions. The complete source code you can download here “Windows Phone PC Connector“.

Windows Phone – Daily Horoscope Example

Do you believe on horoscope? I do not but my wife does. Sometimes she watches in Internet some predictions about her horoscope and tells me that they are not correct in her case. But in most of cases it was correct and she believes it a lot. She says me that everyone has his own fate and man can not change or something likes that. I always say she should be a fortuneteller. She will earn millions of dollars from this career. ^^. Although I do not believe on horoscope but today I decide to write a small application on Windows Phone to tell user his daily horoscope. With this application I would like to test if I can use DependencyObject to create a custom image button control. The result is ” I failed”. In WPF I can easily create a image button with RelativeSource and AncestorType but Silverlight and Windows Phone do not support it. There is work around with DependencyObject but I still do not know how to do it. So if you know how to make a custom image button control in Windows Phone then please tell me.

The application is very simple. It just fetches data from a RSS feed under XML format and gives information back to GUI. Because I failed with create a custom image button therefore my XAML file looks very terrible as following

<StackPanel Orientation="Vertical">
	<Rectangle Height="25"></Rectangle>
	<StackPanel Orientation="Horizontal">
		<StackPanel Style="{StaticResource CustomSPStyle}" Orientation="Vertical">
			<Image MouseLeftButtonDown="imgAries_MouseLeftButtonDown" x:Name="imgAries" Style="{StaticResource CustomImageStyle}" Source="Images/DuongCuu.jpg"></Image>
			<TextBlock Style="{StaticResource CustomTBStyle}" Text="Aries"></TextBlock>
		</StackPanel>
		<StackPanel Style="{StaticResource CustomSPStyle}" Orientation="Vertical">
			<Image MouseLeftButtonDown="imgTaurus_MouseLeftButtonDown" x:Name="imgTaurus" Style="{StaticResource CustomImageStyle}" Source="Images/KimNguu.jpg"></Image>
			<TextBlock Style="{StaticResource CustomTBStyle}" Text="Taurus"></TextBlock>
		</StackPanel>
		<StackPanel Style="{StaticResource CustomSPStyle}" Orientation="Vertical">
			<Image MouseLeftButtonDown="imgGemini_MouseLeftButtonDown" x:Name="imgGemini" Style="{StaticResource CustomImageStyle}" Source="Images/SongTu.jpg"></Image>
			<TextBlock Text="Gemini" Style="{StaticResource CustomTBStyle}"></TextBlock>
		</StackPanel>
	</StackPanel>
	...
</StackPanel>

You can see that I use StackPanel to store my custom control consisting of an image and a textblock. For each horoscope I add such StackPanel and it is really stupid to do that because when I want to apply style for textblock/image, I must apply it for every textblock/image through copying and pasting. Because I am stuck in creating such control like this http://blogs.msdn.com/mikehillberg/archive/2007/02/01/ParameterizedTemplates.aspx , this is current status. I will update the code if I find a solution. The remaining code is really easy. It is combination of navigating between pages, getting data from web client and parsing data,… etc. Nothing special.

private void imgLeo_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
	NavigationService.Navigate(new Uri("/Astrology.xaml?Horoscope=Leo", UriKind.Relative));
}
...
void wcTemp_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
	try
	{
		XDocument doc = XDocument.Parse(e.Result);
		var vGotArticle = (from s in doc.Descendants("item")
						   select new Horoscope
						   {
							   Title = s.Element("title").Value,
							   Description = TrimAndRemoveNewLine(s.Element("description").Value.ToString()),
						   });
		m_lstHoroscope = vGotArticle.ToList();

		if (m_lstHoroscope.Count > 0)
		{
			var vFound = (from h in m_lstHoroscope
							   where h.Title.IndexOf(m_strHoroscope) >= 0
							   select h).FirstOrDefault();
			HoroscopeImage = GetImageUri(m_strHoroscope);
			NotifyPropertyChanged("HoroscopeImage");
			HoroscopeDescription = vFound.Description;
			NotifyPropertyChanged("HoroscopeDescription");
		}

	}
	catch (Exception ex)
	{
		throw ex;
	}
}

The complete source code of this example you can download here “Windows Phone Horoscope

Windows Phone – Progress popup and AutoCompleteBox

Progress popup
During my development I would like to have a progress popup which shows a dialog telling the user that the program are on working process. The implementation below does not contain a progress bar if you want to can insert a progress bar and update it.

<Popup x:Name="ProgressPopup"
			Width="300"
			IsOpen="False" HorizontalAlignment="Center" VerticalAlignment="Top" d:LayoutOverrides="Width, HorizontalMargin" Margin="89,203,91,0">
	<Border BorderThickness="10"
				BorderBrush="Black"
				Background="DarkGray"
				Padding="30,30">
		<StackPanel>
			<TextBlock Foreground="White"
						FontWeight="Bold"
						FontSize="36"
						x:Name="txt"
						Text="Processing...">
						<TextBlock.Triggers>
							<EventTrigger RoutedEvent="TextBlock.Loaded">
								<BeginStoryboard>
									<Storyboard>
										<DoubleAnimation
											AutoReverse="True"
											Duration="0:0:1"
											From="1.0"
											RepeatBehavior="Forever"
											Storyboard.TargetName="txt"
											Storyboard.TargetProperty="Opacity"
											To="0.0"/>
									</Storyboard>
								</BeginStoryboard>
							</EventTrigger>
						</TextBlock.Triggers>
			</TextBlock>
		</StackPanel>
	</Border>
</Popup>

I also add an animation to make the opacity to 0.0 so that I can have a blinking text block. To call this popup, you can use following code to turn on and turn off popup.

this.Dispatcher.BeginInvoke(new Action(() => ProgressPopup.IsOpen = true));
this.Dispatcher.BeginInvoke(new Action(() => ProgressPopup.IsOpen = false));

AutoCompleteBox
The second component I would like to discuss in this post is AutoCompleteBox. If you are developers on Silverlight, you may know there is already a AutoCompleteBox control. However this control is not available on Windows Phone. So if you would like to use this control in Windows Phone, you can simply add reference to the library of this control. After installing Silverlight SDK, the library of AutoCompleteBox should be at “C:\Program Files (x86)\Microsoft SDKs\Silverlight\v3.0\Libraries\Client\System.Windows.Controls.Input.dll” (your installation path may vary from mine). Let’s add reference to add and add one instance in page

<phoneNavigation:PhoneApplicationPage
    ...
    xmlns:swci="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input"
    ...
    Loaded="PhoneApplicationPage_Loaded"
    >
...
<Grid x:Name="ContentGrid" Grid.Row="1">
	<swci:AutoCompleteBox x:Name="acbName" Margin="0,6,0,564"></swci:AutoCompleteBox>
</Grid>

Add database for AutoCompleteBox

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
	List<string> lstNames = new List<string>();
	lstNames.Add("Lewis");
	lstNames.Add("Whitcomb");
	lstNames.Add("Kadi");
	lstNames.Add("Woods");
	lstNames.Add("Shissler");
	lstNames.Add("Fleischer");
	lstNames.Add("Johnson");
	lstNames.Add("Schloen");
	lstNames.Add("Ritner");
	lstNames.Add("Pardee");
	acbName.ItemsSource = lstNames;
}

The AutoCompleteBox will work perfectly in Windows Phone

Windows Phone – Use REST WCF Service

Today when I play around with development in Windows Phone 7. I would like to check if I can access WCF REST Service which I discussed before in this post http://hintdesk.com/wcf-silverlight-access-wcf-rest-services-with-silverlight/ . To start with the development in Windows Phone 7 you need to download set of development tools here http://www.microsoft.com/downloads/details.aspx?FamilyID=2338b5d1-79d8-46af-b828-380b0f854203&displaylang=en . This set contains of
– Visual Studio 2010 Express for Windows Phone CTP
– Windows Phone Emulator CTP
– Silverlight for Windows Phone CTP
– XNA 4.0 Game Studio CTP
This packet is about 350 MB and can be installed parallel with Visual Studio 2008 SP1 and .Net Framework 3.5. When I try to move the example of the old post to Windows Phone 7, I think it must be very simple because the old example bases on Silverlight and Windows Phone 7 uses Silverlight as its default template and I am right. During the moving, I just need to copy and paste the code behind without needing to change anything. However some of components in normal Silverlight are not available, for example Label and DataGrid. The label can be easily replaced by a TextBlock but we need more work to make a control to replace DataGrid. I make a snapshot of available controls in image below

Continue reading Windows Phone – Use REST WCF Service

Windows Phone – Binding Converter

When I make a small application to read RSS feed on Windows Phone 7, I discover that in current version of windows phone 7 framework the attribute ValueConversionAttribute is not supported so I can not make a binding converter when working with XAML. Therefore I would like to make a reverse engineering to steal the source code of ValueConversionAttribute in .Net Framework 3.5 and use it in my application. Because I am lazy to invent a new example to demonstrate, I would like to use the example from this link http://learnwpf.com/Posts/Post.aspx?postId=05229e33-fcd4-44d5-9982-a002f2250a64 and adjust it so that it should work on Windows Phone 7 too.

Because the example is exactly same as the original one, I will tell which I changed to make it run on Windows Phone 7. First, the ObjectDataProvider is not provided in Windows Phone 7 therefore I must remove the DataContext of the ListBox and keep only databinding of ItemsSource and bind it with list of data objects

private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
	ObservableCollection<SaleRecord> salesData = new ObservableCollection<SaleRecord>();
	salesData.Add(new SaleRecord(1001, System.DateTime.Now.Subtract(new TimeSpan(1, 1, 1)), 123.4m, 0.045f));
	salesData.Add(new SaleRecord(1002, System.DateTime.Now.Subtract(new TimeSpan(1, 0, 0)), 42m, 0.09f));
	salesData.Add(new SaleRecord(1003, System.DateTime.Now.Subtract(new TimeSpan(0, 58, 0)), 10.99m, 0.09f));

	lvData.ItemsSource = salesData;
}

and then remove the “sales” resource from resources section

<phoneNavigation:PhoneApplicationPage.Resources>
	<my:FormattingConverter x:Key="formatter" />
</phoneNavigation:PhoneApplicationPage.Resources>

As I told above, ValueConversionAttribute is not supported in Windows Phone 7. Therefore I must steal from .Net Framework 3.0 and it looks like following

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
public sealed class ValueConversionAttribute : Attribute
{
	// Fields
	private Type _parameterType;
	private Type _sourceType;
	private Type _targetType;

	// Methods
	public ValueConversionAttribute(Type sourceType, Type targetType)
	{
		if (sourceType == null)
		{
			throw new ArgumentNullException("sourceType");
		}
		if (targetType == null)
		{
			throw new ArgumentNullException("targetType");
		}
		this._sourceType = sourceType;
		this._targetType = targetType;
	}

	public override int GetHashCode()
	{
		return (this._sourceType.GetHashCode() + this._targetType.GetHashCode());
	}

	// Properties
	public Type ParameterType
	{
		get
		{
			return this._parameterType;
		}
		set
		{
			this._parameterType = value;
		}
	}

	public Type SourceType
	{
		get
		{
			return this._sourceType;
		}
	}

	public Type TargetType
	{
		get
		{
			return this._targetType;
		}
	}
}

To use it just put it above your class

[ValueConversion(typeof(object), typeof(string))]
public class FormattingConverter : IValueConverter
{
	...
}

In the code of ValueConversionAttribute, I removed a override property. The absence of this property can cause program to crash (maybe). So use it on your risk and wait for a new version of framework for Windows Phone 7. The complete source code you can download here “Windows Phone Binding Converter

Windows Phone – Rss Reader software on Windows Phone emulator

This is the first software I write on Windows Phone 7. I have a lot of RSS feeds to read therefore I would like to have a RSS reader on Windows Phone 7 to manage all feeds(if I have one Windows Phone 7 in future ^^). This RSS reader provides some basic functions so that I can add, remove a feed. For each feed there are read and unread items. The unread items will be marked with Magenta, the read one will be marked with White. After finishing the beta version of this software, I would like to deploy it so that the others can use it on their emulator too but I find out until now there is no possibility to do that.

Continue reading Windows Phone – Rss Reader software on Windows Phone emulator

Windows Phone 7 – Simple database example

Today when I start to play around with developing on Windows Phone 7, I would like to write a first small database application because Windows Phone does not support SQL Server any more. Therefore I must use either LINQ over XML or store the database somewhere on server/Windows Azure and provide services so that the client can access and make query to get and update data. In this small example, I would like to work with LINQ To XML to create a database and update it.

My data object (data entity) is a class of Student with his first name, last name and email built by appending first name and last name as describing below

Continue reading Windows Phone 7 – Simple database example

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