Read Microsoft Visual C# 2005 Express Edition: Build a Program Now! Online
Authors: Patrice Pelland
Tags: #General, #Computers, #C♯ (Computer program language), #Programming Languages, #C#, #Microsoft .NET Framework, #Computer Books: Languages, #Computer Graphics, #Application software, #C# (Computer program language), #Programming, #Microsoft Visual C# .NET, #Microsoft Visual C♯ .NET, #Electronic books, #Game Programming & Design, #Computing: Professional & Programming, #C (Computer program language), #Computers - Languages, #Programming Languages - C#, #Programming & scripting languages: general
all of the controls on the form by creating a large
selection rectangle around them with your mouse.
In the Properties window, set the BorderStyle from
14 Using Figure 9-8 as a guide, size and position
None to
FixedSingle
. Black borders should appear
the controls on the form. If you want, adjust
around all controls. Once the form is done, we’ll set
the font size and style of the labels.
the BorderStyle back to None.
On the PictureBox control, set the Name
9 property to
pbCurrentTemp
, set the
BackColor property to
Web:White
, set the Size.
Width to
55
, and set Size.Height to
45
.
Figure 9-8
Layout of the current weather
information
184
Microsoft Visual C# 2005 Express Edition: Build a Program Now!
CSX_Chapter 9.indd 184
CSX_Chapter 9.indd 184
10/24/05 6:59:26 PM
10/24/05 6:59:26 PM
User Settings
For the Weather Tracker application to work, you will need to specify your weather Web service registration information. Your username and password will be saved in the application settings. The application settings are settings stored in an XML file and persist from one execution to another. The current ZIP code will also be saved here.
TO CREATE USER SETTING ENTRIES
In the Solution Explorer, right-click the
Weather Tracker
project and select
Properties
. The Project 1 Designer appears.
Figure 9-9
Application settings in the Project
Designer
In the Settings tab, add entries for
Username
,
Password
, and 2
CurrentZipCode
as shown in Figure 9-9. (You will need to specify your own username and password.)
All entries are strongly typed (i.e., real .NET type) and set to string type. You might be alarmed by the fact that Username and Password are in clear text. In your case, you don’t need a great deal of security because the weather Web service is a free service. If you had to, you could encrypt those settings to make them more secure.
3 Save your project and close the Project Designer.
Working in the Background
If you try to run your form now, you won’t get anything from the Web service. This process differs from your work with databases, in which a great deal of code was completed for you so you could retrieve the data and populate the fields. When dealing with a Web service, you must do more of the actual coding to get the data into the form. Let’s talk about how you’ll do this.
Chapter 9: Build Your Own Weather Tracker Application Now!
185
CSX_Chapter 9.indd 185
CSX_Chapter 9.indd 185
10/24/05 6:59:27 PM
10/24/05 6:59:27 PM
First, talking to a Web service can be a long process. A long process typically means only
The following sections contain
a few seconds (perhaps up to 30 seconds), but you can’t leave the user with a blocked UI
quite a bit of code. If you don’t
want to type this code, you can
while your application is retrieving information. You therefore need a way of saying to your
open the completed Weather
application: “Go get this information and let me know when you have it.” This programming
Tracker project in the companion
content and copy the sections of
technique is called multithreaded programming with call backs. In .NET Framework 2.0, this
code as needed.
type of programming is simplified by creating a new class called the BackgroundWorker class. As its name implies, it works in the background on a task; what’s not implied is that it will let you know when it has completed the task.
TO PERFORM A TASK IN THE BACKGROUND
1 Open the
Main
form in design view.
Go to the
Toolbox
. In the Components section, select the
BackgroundWorker
control and drag it 2 onto your form. It doesn’t have a design time portion, so it will be added to the component tray. Rename it
backgroundCurrentWorker
.
At the top of the Properties window for backgroundCurrentWorker, click the events icon (yellow light3 ning) and then double-click the
DoWork
event. 4 At the top of Main.cs, add the following using statements to the existing using statements. 1 using Weather_Tracker.Properties;
2 using Weather_Tracker.WeatherWebService;
5 Add the following code to the backgroundCurrentWorker_DoWork event handler. 3 private void backgroundCurrentWorker_DoWork(object sender, DoWorkEventArgs e) 4 {
5 // This method will execute in the background thread created by the 6 // BackgroundWorker component
7 int desiredZipCode = (int)e.Argument;
8 Service weatherService = new Service();
9 e.Result = weatherService.GetWeatherInfo2(
10 Settings.Default.Username,
11 Settings.Default.Password,desiredZipCode);
12 }
186
Microsoft Visual C# 2005 Express Edition: Build a Program Now!
CSX_Chapter 9.indd 186
CSX_Chapter 9.indd 186
10/24/05 6:59:27 PM
10/24/05 6:59:27 PM
The DoWork event handler is where the call to the weather Web service is performed. You will start by calling the GetWeatherInfo2 method exposed by the Web service. When you invoke the GetWeatherInfo2
method, it runs in a separate context so that it doesn’t block the application UI. Otherwise, the application might appear to hang.
The GetWeatherInfo2 method takes three parameters (username, password, ZIP code) and returns a WeatherInfo result. How do you know what parameters you need and the return value? You can look at the WSDL (pronounced WISDLE) file to understand. Also, when you added the weather Web service, Visual Studio generates the appropriate IntelliSense.
6 Add the following startBackgroundTaskCurrentDay method.
13 private void startBackgroundTaskCurrentDay()
14 {
15 try
16 {
17 // Execute the background task only if it’s not already working 18 if (!backgroundCurrentWorker.IsBusy)
19 {
20 this.UseWaitCursor = true;
21 this.backgroundCurrentWorker.RunWorkerAsync(
22 int.Parse(currentZipCode));
23 }
24 }
25 // Normally an exception handling class or logging would be used, 26 // but we’ll just use a message box.
27 catch (FormatException)
28 {
29 MessageBox.Show(“Invalid conversion from string to int”,
30 “Parse Zip Code Exception”);
31 throw;
32 }
33 catch (Exception)
34 {
35 MessageBox.Show(“Fatal Error!”,
36 “Fatal error starting background task”);
37 throw;
38 }
39 }
Chapter 9: Build Your Own Weather Tracker Application Now!
187
CSX_Chapter 9.indd 187
CSX_Chapter 9.indd 187
10/24/05 6:59:28 PM
10/24/05 6:59:28 PM
The startBackgroundTaskCurrentDay method starts the BackgroundWorker. The first thing you need to do is verify whether the BackgroundWorker is already busy with a previous call; if you don’t do this, you’ll end up with an InvalidOperationException. Simply verifying whether the BackgroundWorker is busy ensures that you won’t get that exception when calling the RunWorkerAsync method. In fact, this is the only exception that this method can raise. A quick look at the documentation can confirm this. Executing the RunWorkerAsync method is submitting a request to start an operation asynchronously, which raises the DoWork event. An event handler with the following name format is invoked:
7 Switch to Design view and select
backgroundCurrentWorker
in the component tray. 8 In the events list in the Properties window, double-click the
RunWorkerCompleted
event. 9 Add the following code to the BackgroundCurrentWorker_RunWorkerCompleted event handler. 40 private void backgroundCurrentWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
41 {
42 if ((e.Error == null))
43 {
44 this.UseWaitCursor = false;
45 WeatherInfo weatherInfo;
46 weatherInfo = (WeatherInfo)e.Result;
47 weatherInfoBindingSource.DataSource = weatherInfo;
48 pbCurrentTemp.Load(@”.\Images\” +
49 weatherInfo.IconIndex.ToString() + “.gif”);
50 // If web service returned weather info, then
51 // update notify icon
52 currentTemperature = this.ExtractTemperature();
53 this.CreateIcon((int)Math.Round(currentTemperature));
54 }
55 else if ((e.Error.Message.IndexOf(“503”) > 0))
56 {
57 MessageBox.Show(
58 “Weather Web service is unavailable, retry later!\n” +
59 “Retry later using the Refresh Weather Info menu.”,
60 “Weather Web service unavailable”);
188
Microsoft Visual C# 2005 Express Edition: Build a Program Now!
CSX_Chapter 9.indd 188
CSX_Chapter 9.indd 188
10/24/05 6:59:29 PM
10/24/05 6:59:29 PM
61 }
62 else if ((e.Error.Message.IndexOf(“timed out”) > 0))
63 {
64 MessageBox.Show(
65 “Unable to retrieve the data in the time allowed\n” +
66 “Retry later using the Refresh Weather Info menu.”,
67 “Weather Web service Timeout”);
68 }
69 else
70 {
71 MessageBox.Show(
72 “Problem with Weather Web service! Error message:\n” +
73 e.Error.Message + “ \nRetry Later!”,
74 “Weather Web service problem”);
75 }
76 }
If the Web service was available and your parameters were good, the method you invoked is then working in a different context and on its own. When it is finished with its business, you will be notified that the method has completed because a RunWorkerCompleted event will be raised. To retrieve the results, you must have an event handler with the following name:
Chapter 9: Build Your Own Weather Tracker Application Now!
189
CSX_Chapter 9.indd 189
CSX_Chapter 9.indd 189
10/24/05 6:59:30 PM
10/24/05 6:59:30 PM
In your case, if you look into the method signature for GetWeatherInfo2, WeatherInfo is the type of results it is producing. Therefore, you need to declare a variable of that type.
You may be wondering: What
If you recall, when you dragged the WeatherInfo dataset onto the designer surface, you
is the link between the index
automatically created databound controls for all of those fields. Thus, you simply need to
and the filename, and who is
assign that WeatherInfo variable as the DataSource for your BindingSource, and you will
creating that link? This is a con-
vention used by many weather
have a link between what’s coming from the Web service and the controls on your form.
providers on the Internet; there-
Now, you also have a picture box on the designer surface that will serve to display an
fore, this is something that will
icon portraying the current forecast. The info is returned to you as an index: the iconIndex
work with many services if you
property. You need to load an image file from your hard drive into the picture box you
want to add some later.
dragged onto the designer surface using the index as the filename.
What happens next is the creation of the icon that will appear in the notification area representing the current temperature.
TO ADD SUPPORTING BACKGROUND CODE