Windows 10 IOT: Windows Forms to XAML/C# & Webservices

Sample code can be found at my GitHub Repo.

In the Windows 10 developer universe, you can develop once and have your product work across a large number of devices, and if done correctly you will not require any changes.  In this blog we will use XAML/C# to connect to a weather service to retrieve the reporting countries and then related cities, we won’t do the weather in this blog, that will be in another blog.

The final product will work in both Windows 10 on the Desktop/Tablet and the Raspberry Pi!  Pretty cool right?  This means that you could develop a cool cash register app that includes several features and be able to design it to work with smartphones, embedded systems like the Raspberry Pi and tablets for kiosks.  Do all of that without changing any of the code base, and if you design the UI correctly you might not even have to change the UI.

In the example that I will provide with this blog, you will see how to use WebServices, understand why not to use Win Forms, and see your app working on the Raspberry Pi.  You will not learn how to create a beautiful app, for that you need to go to Jerry Nixon’s blog, and you can see his blog is much more beautiful than mine.  Over the next few blogs I will definitely be referencing his blog for things like data binding, which is the reason we will not be pulling the weather data out of the WebServices.

Exception to UWP

There is one exception: Forms.  If you are required to use Windows Forms at work, well that is one thing, but you really need to get up to speed on XAML/C# or XAML/C++ (except for Jerry Nixon).  If you are a student you may attend a school that teaches their UI classes using Windows Forms.

The UWP or Universal Windows Platform is an amazing offering and concept for the designer, investors, researchers, hobbyists and students!  One of the amazing things is Windows 10 running on the Raspberry Pi, and it runs quite nicely.  Sadly, Windows Forms do not really work in this scenario, and this blog entry will show some of the changes that you may encounter. Let’s see what you need to be aware to make a change.

Now let’s begin our exploration of how you can use Windows 10 to develop IOT apps on the Raspberry Pi.

Where is the code for this app? See the GitHub Repo.

Where does the Raspberry Pi fit into the Universal Windows Platform (UWP)

Here is a diagram of part of the UWP family, the ellipse indicates that there are more in the family, for example PixelSense devices that represent a high end market that actually pays for software! (Image from Guide to Universal Windows Platform (UWP) apps.)  As you can see the Raspberry Pi fits nicely into the IoT device family with a head or headless..  The IoT device with a head has a screen and GUI, the headless device family would use a two-line LCD display or maybe just LEDs that are on or off.  You would use the head device for a cash register and the headless might be used for a pinball machine with bright LEDs and old fashioned mechanical displays.

Device families

So the Raspberry Pi could consume a GUI designed correctly that works on the Windows Phone (or an Android device that allows me to run Windows 10 instead of the Android operating system), a mobile device like a Surface 3.  And use the same code!  The code can be written in C#, C++ or Visual Basic.

One of the issues you may have is that you are familiar with Windows Forms and not XAML/C# or JavaScript.  Let’s look at how you can fairly easily change your design process from Windows Forms to Windows 10 using XAML/C#.

Back to the Forms issue: Why to move from Windows Form Code to XAML/C#

Let’s say you are excited about developing a simple windows form to get certain data from the web and you found a brief series of well done YouTube videos, for example: C# Tutorial | Weather Application Part 1 | Web Services | Creating the Windows Form that shows you how to use Windows Forms with web services to get weather.  You check the date of the YouTube video and it seems like it is up to date, it’s  publication date is August 8, 2015, and the author does a great job, for Windows Forms.  Unfortunately Windows Forms will not deploy to other devices and will only deploy to the Desktop  version of Windows 10.

Why? The design concept behind Windows Forms targets the operating system, UWP targets device families.   I used the referenced video to design my response to Forms, and the referenced video which was well done, if you are focused on using Forms.

Windows Forms allow you to make bad decisions like not using asynchronous coding, asynchronous coding is available in Windows Forms, for example if you use Windows Forms with a REST based Web Services, like the weather web service at https://www.webservicex.com/globalweather.asmx, the form project offers reference objects, that are both Async and non-Async.  Non-async apps are unresponsive apps and are not appreciated by app designers, but your manager might like them, so there is that.  If you look at the same screen with the XAML/C# UWP app, note that the XAML C# offering is much richer and guides you to better practices. (You may need to click on the images to see the differences between Forms and XAML/C#.)  For example, you can only use the Async objects in the XAML/C# project.

Form Service Reference offerings (Scroll down to see the comparable XAML/C#)
image
XAML C# Service Reference Offerings
image

When you complete the reference video the code  which will only work on the Windows Client, and that might meet your immediate goal.  WinForms won’t work on the Raspberry Pi, and if it doesn’t work on the Raspberry Pi, you miss out on 2 million potential customers!  Not sure how well those customers pay, but still, even 1% is still 20,000 potential customers.

Of course, if you have been using WPF, then you are dialed in.  You should have no problem and should go to Jerry Nixon’s blog immediately, after all he is the platinum guy these days!

Using Windows 10 XAML/C# for web services

Async Await and more stuff to learn like Lambdas.  If you have been avoiding the use of asynchronous tools, then this is the blog for you!  As to Lambdas, see the actual code for comments, but seriously, you need to learn them.  Get started here:

For the code, go to the GitHub Repo (or is it Repro), there are many comments in the code to help you out, if you need it.

To keep sample app simple and to avoid adding too many concepts, I will only return the Countries and Cities from https://www.webservicex.com/globalweather.asmx, the actual weather will be used in a future blog to demonstrate data binding.

The process might look like this:

image

How to use Asynchronous Code, may seem overly complex, asynchronous code is in reality easy to use!

The use of asynchronous in the cloud is a necessity for any programmer, see the fully commented  code can be found at https://github.com/SocalSam/codewebservices/.

Asynchronous code is fairly simple, let’s look at it:

  • Add the async keyword to the function or event:
    • Example: private async void button_Click(object sender, RoutedEventArgs e)
  • Run the async web object, this is supplied on the web server:
    • Example: Task<string> getCities = gwsc.GetCitiesByCountryAsync("");
  • Now set up the “await” keyword, once this keyword is fired the function will stop working, so you must put other functions calls before the await:
    • Example: string citys = await getCities;
  • Once your variable is filled, then you have to operate on the data so that it is useful for the program and end user or autonomous program, for the Weather data, it is in an XML format so you likely want to deserialize your data.  This is easy once you have done it a number of times, but difficult to get the flow the first few times.
    • Set a breakpoint one statement past the statement that does the deserialization
    • If you see something that looks like: getCities = Id = 33, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
      • You need to see if your statement with the “await” keyword is correct.
      • This may indicate that the webservice did not respond, so run the code again
    • In the Autos you will see your variable that is holding the return data, in the case of my code it is the misspelled word: citys and using the dropdown list on the Autos:
    • image
    • The Text Visualizer will show you something like the following:
    • image
    • Now copy the Value of the Text Visualizer
    • Create a new class, name it cities.cs to match my code.
    • In the Class, use the menu item “Edit” and then “Paste Special”, select “Paste XML as Classes”
    • image
    • Once you hit the Paste Special Visual Studio will add your XML in a format that can be used by your code!  Big savings in time!  To see what the automatic code looks like see cities.cs in the code at: GitHub Repo.
    • Now you can perform your deserialization and find the cities in countries
    • The code below captures the dataset and then generates a serial format in the variable “result” which acts as the XML Schema, which the StringReader reads out of the variable citys the string with the XML Data is deserialized into the object cn.  The deserialized data must be operated on to prevent multiple countries being shown and this is accomplished with a Lambda anonymous function that uses standard query operator, where the table is selected and the unique or distinct countries are returned.
      1. string citys = await getCities;
      2. XmlSerializer result = new XmlSerializer(typeof(cities.NewDataSet));
      3. cn = (cities.NewDataSet)result.Deserialize(new StringReader(citys));
      4. var Countries = cn.Table.Select(m => m.Country).Distinct();
    • See the code attached to this blog for more comments.

Code Maps:

The bulk of the code map shows how the elements in the code looks (click to enlarge):

image

The cities.cs class has this code map, the class code is created automatically by Visual Studio, which saves time but if you want to build your own code, there is no reason not to, if you have time.

image

Running on the Raspberry Pi

Now, let’s run this on the Raspberry Pi, (apologies for the poor images, I still have not written the clever code to do screen shots on the Raspberry Pi):

  1. Test that your app works in Windows 10 from Visual Studio.
  2. Load the Windows 10 IOT on an SD card using the instructions at: https://ms-iot.github.io/content/en-US/GetStarted.htm
    • Note: If you encounter an error statement while attempting to connect to your Raspberry Pi from Visual Studio 2015 that looks like this:
      • APPX4001: Build property AppxBundlePlatforms is not explicitly set and is calculated based on currently building architecture. Use 'Create App Package' wizard or edit project file to set it.
      • This error likely can be solved by removing your SD card from the Raspberry Pi and reloading your IOT image on it, at least it did with mine.
  3. Make sure your connections are all working by using the “Blinky” app, you don’t need to build the LED  circuit, your monitor will show the “Blinky” app if it works which is a big red dot will flash on and off on the HDMI Screen you are using with the Raspberry Pi.
    • Why?  This is a confidence test that shows you that your Pi is connected to your development machine.
  4. You are now ready to load your app to the Raspberry Pi, don’t worry about the Blinky app, the Webservices app will run instead of the Blinky app.  Use the same process that you did with the Blinky app.
  5. It will take a few minutes for the app to build and deploy, be patient as long as there are no indications in Visual Studio that the connection isn’t working.
  6. Once the app loads to the Raspberry Pi, you will see something that looks like the following (and it isn’t a pretty app, just functional), the combo boxes won’t be loaded, you will need to click on the button with a mouse, and then the combo boxes load up, when you click on the drop down arrow you should see the countries, make sure to do the countries first, then cities.
    • Trouble-shooting: If the country combo box is empty when you click them, after clicking the button, this may mean that the web service is slow, wait a few seconds and click the button again.
    • Images taken by camera, not screen shots from the Raspberry Pi, the first image is what you should see on your Raspberry Pi.
    • IMG_0473
    • IMG_0471

Conclusions

Windows Forms are used by many designers and tutorial creators on the web.  Windows Forms trap you into only being able to implement design solutions for the desktop Windows 10.  UWP allows you to design once and be confident that you can reuse the app on many devices.

We did not go over how to make sure your UI looks good on MANY devices.  That will be another blog.

Also, we covered how to use Web Services in your apps, and the examination of how to do the Web Services also demonstrated that code written for Desktop Windows 10, works just well in the Raspberry Pi.  This means you will be able to implement Azure based processing and then serve the computational results to the low powered Raspberry Pi.  It also means that you could use the DreamSpark/Imagine web app/site to set up and provide WebServices to your Raspberry Pi, and others could also use it.

image