Microsoft Visual C# 2005 Express Edition: Build a Program Now! (42 page)

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

BOOK: Microsoft Visual C# 2005 Express Edition: Build a Program Now!
13.82Mb size Format: txt, pdf, ePub

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

N O T E

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: _DoWork. In your case, the backgroundCurrentWorker_DoWork method is executed when the DoWork event is raised.

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: _RunWorkerCompleted. In this method, you have a parameter of type RunWorkerCompletedEventArgs that contains everything you need to obtain the results. If an exception was raised in the DoWork event handler, you’ll be able to retrieve it by checking the Error property, which is of type Exception. If there is no error, then you must retrieve the results yourself. Remember that the Results property will give you an element of type Object, which by itself will not help you. You need to assign it a variable with the same type that the Web service method used to spit out the results.

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

Other books

River of Lies by Sammy King
The Doll by Daphne Du Maurier
Leashed by a Wolf by Cherie Nicholls
Hire a Hangman by Collin Wilcox
WindBeliever by Charlotte Boyett-Compo
Hung: A Badboy Romance by Cruise, Carolyn
Los hijos de Húrin by J.R.R. Tolkien
Spies: The Rise and Fall of the KGB in America by Harvey Klehr;John Earl Haynes;Alexander Vassiliev