Friday, August 26, 2016
Monday, July 13, 2015
WPF ProgressBar IsIndeterminate behavior
Today I found that hiding (collapsing) a WPF ProgressBar control with IsIndeterminate set to true does not stop the control from using the CPU. I am using this control in the status bar of a WPF application as a visual hint to the user that some background task is progressing, a sign that the application is busy.
My approach was simply to show or hide the control with the IsIdeterminate property preset to True in XAML, by binding to the Visibility property. This proved painfully wrong while testing on a colleague's notoriously slow PC - while idling the application was using CPU (way too much).
Interestingly, when you first create the control in collapsed state, the animation is not enabled, only when it is displayed. After that, the animation code seems to be running all the time. My solution was to bind the same boolean property used to show or hide the control to the IsIndeterminate property. This way I managed to get the CPU down to zero while idling, the way I thought it should be.
The funny part is that this control was also being used on a grid to display the loading status of the underlying list of elements. Ouch...
My approach was simply to show or hide the control with the IsIdeterminate property preset to True in XAML, by binding to the Visibility property. This proved painfully wrong while testing on a colleague's notoriously slow PC - while idling the application was using CPU (way too much).
Interestingly, when you first create the control in collapsed state, the animation is not enabled, only when it is displayed. After that, the animation code seems to be running all the time. My solution was to bind the same boolean property used to show or hide the control to the IsIndeterminate property. This way I managed to get the CPU down to zero while idling, the way I thought it should be.
The funny part is that this control was also being used on a grid to display the loading status of the underlying list of elements. Ouch...
Wednesday, October 23, 2013
Layout Cycle Detected - My story
If you are reading this then probably you hit one of the Silverlight errors I dread the most. Sometimes you see an error message, other times your screen just goes blank. Once I managed to intercept an exception in Visual Studio's debugger, but that was a very lucky shot.
There are a few links on the web that explain what is going on, and I followed this one on StackOverflow which proved to help me a lot. In my case I have a relatively complex Gantt chart -like user control that allows for zooming and scrolling. Individual Gantt items are also relatively complex user controls that need to be re-sized when the parent control is itself re-sized or when the user zooms in or out.
My initial implementation approach, which proved to be reliable on early tests, was to use the Gantt item child user control's SizeChanged event to re-size and re-position internal elements. As I said, this proved to work reliably with a limited number of items. When I started to test the main control with real live data, the problem emerged.
The fault was on the design itself - you should never change the size of your user control inside the user control's SizeChanged event. Never. This will trigger a recursion loop that the layout engine may never recover from and you will get the dreaded exception, or blank screen.
My solution was very simple - I moved all of the code from the event handler to a public method that is called from the parent control's code. This works well because there is no other instance that re-sizes the child control but its parent, so there is only one entry point for calling the code. Instead of assigning a value to the children's Width property, now the parent user control code calls a SetWidth method on the child that besides setting the width, also executes the re-sizing logic outside the SizeChanged event handler. Voilá.
There are a few links on the web that explain what is going on, and I followed this one on StackOverflow which proved to help me a lot. In my case I have a relatively complex Gantt chart -like user control that allows for zooming and scrolling. Individual Gantt items are also relatively complex user controls that need to be re-sized when the parent control is itself re-sized or when the user zooms in or out.
My initial implementation approach, which proved to be reliable on early tests, was to use the Gantt item child user control's SizeChanged event to re-size and re-position internal elements. As I said, this proved to work reliably with a limited number of items. When I started to test the main control with real live data, the problem emerged.
The fault was on the design itself - you should never change the size of your user control inside the user control's SizeChanged event. Never. This will trigger a recursion loop that the layout engine may never recover from and you will get the dreaded exception, or blank screen.
My solution was very simple - I moved all of the code from the event handler to a public method that is called from the parent control's code. This works well because there is no other instance that re-sizes the child control but its parent, so there is only one entry point for calling the code. Instead of assigning a value to the children's Width property, now the parent user control code calls a SetWidth method on the child that besides setting the width, also executes the re-sizing logic outside the SizeChanged event handler. Voilá.
Tuesday, January 10, 2012
Silverlight, Library Caching and blank screens
Here's the scenario: You have a Silverlight 4 application with a splash screen. You business is growing and so is your Silverlight application's xap size. What can you do about it? Wouldn't it be nice if you could somehow split the xap into smaller and reusable files? This is exactly what the "Library Caching" feature is supposed to do: your reusable libraries are packaged into zip files and stored in your browser's cache, reducing the initial download bandwidth.
Theoretically all works well, of course. Until your customers start complaining about blank screens after the xap is downloaded on IE9. To get the application to start, they have to press F5 once (sometimes more). A brief internet search shows that this is a known and reported issue, but as you can see it's solved because Microsoft cannot reproduce it.
So now I have to go back and recompile the xap as a monolith to avoid this nice little feature that only "works" on IE9. How dumb is this?
Theoretically all works well, of course. Until your customers start complaining about blank screens after the xap is downloaded on IE9. To get the application to start, they have to press F5 once (sometimes more). A brief internet search shows that this is a known and reported issue, but as you can see it's solved because Microsoft cannot reproduce it.
So now I have to go back and recompile the xap as a monolith to avoid this nice little feature that only "works" on IE9. How dumb is this?
Saturday, February 12, 2011
The skewed accelerometer
What can you do if your WP7 accelerometer is not correctly calibrated? As I found out, there seems to be no OS mechanism to calibrate the accelerometer. So if you have a production device you will have to return it for repair or replacement. But what do you do if you have a loaner preproduction device like I do? Well, you have to fix the accelerometer the only way you can: through software.
A correctly calibrated accelerometer should return the vector (0, 0, -1) when you place your device with the screen up on a flat surface (like your office floor). If you have a skewed accelerometer like I do, then you should be able to compensate the difference to the reference vector, once you know what your device is reporting when placed on the floor with the screen up.
To do just that, I wrote a very simple Silverlight application for WP7 that polls the accelerometer every second and displays the vector components, both the sampled value and an average value in order to smooth out the natural variations in the sampling.
You can get the sample application with source code here. After running this app on the floor, I noticed that the Y component of the accelerometer vector was slightly skewed to -0.15, while all other components reported the expected values. After adding 0.15 to the Y component, I got back a calibrated accelerometer.
Now I can get back to my XNA gravity ball code and make it work like it should.
A correctly calibrated accelerometer should return the vector (0, 0, -1) when you place your device with the screen up on a flat surface (like your office floor). If you have a skewed accelerometer like I do, then you should be able to compensate the difference to the reference vector, once you know what your device is reporting when placed on the floor with the screen up.
To do just that, I wrote a very simple Silverlight application for WP7 that polls the accelerometer every second and displays the vector components, both the sampled value and an average value in order to smooth out the natural variations in the sampling.
You can get the sample application with source code here. After running this app on the floor, I noticed that the Y component of the accelerometer vector was slightly skewed to -0.15, while all other components reported the expected values. After adding 0.15 to the Y component, I got back a calibrated accelerometer.
Now I can get back to my XNA gravity ball code and make it work like it should.
Friday, February 11, 2011
MediaElement and downloaded sound
In a nutshell: when you download a sound file to play on a MediaElement, make sure you set the AutoPlay property to True if you call SetSource with the download stream. This stream does not support seeks, so it must play immediately. If you want to store the sound to play it later, store it in a MemoryStream (it supports seeks). I found this out the hard way...
Tuesday, February 8, 2011
The Tabukiniberu bug
This was first presented to me as the "Marshall islands bug": our Silverlight application was opening the Google map in the middle of the Pacific, where it should be showing the mid-Atlantic. Looking closely to the map, I found this extraordinary name: Tabukiniberu, an island in the Pacific near the Equator (the Marshall islands are farther to the north). So what on Earth (literally) was my code doing to spin half the globe and show this (hopefully) beautiful island?
The SL4 app I've been working for in the last 6 months uses both Bing and Google maps AJAX controls due to the different quality of the map content. Google maps are way better on some regions where our business is growing, like Africa and Eastern Europe. On the code side, Bing seems to be better.
When there is nothing to display on the map, the application usually centers on point (0, 0) with a zoom level of 2, providing the "classic" (for my European patterns) wold view with Europe on the top right and the Americas to the left. When there is something to display, the code pans and zooms in to the area of interest so that all pushpins are shown. This particular bug occurs in Google maps code when you call fitBounds on an empty LatLngBounds variable (I mean, initialized but without any added bounds). Instead of showing the mid-Atlantic, you are thrown on a 180 degree spin around the globe to a place very close to Tabukiniberu. Well, at least on the map...
The SL4 app I've been working for in the last 6 months uses both Bing and Google maps AJAX controls due to the different quality of the map content. Google maps are way better on some regions where our business is growing, like Africa and Eastern Europe. On the code side, Bing seems to be better.
When there is nothing to display on the map, the application usually centers on point (0, 0) with a zoom level of 2, providing the "classic" (for my European patterns) wold view with Europe on the top right and the Americas to the left. When there is something to display, the code pans and zooms in to the area of interest so that all pushpins are shown. This particular bug occurs in Google maps code when you call fitBounds on an empty LatLngBounds variable (I mean, initialized but without any added bounds). Instead of showing the mid-Atlantic, you are thrown on a 180 degree spin around the globe to a place very close to Tabukiniberu. Well, at least on the map...
Monday, January 31, 2011
Back to mobile!
I'm back to writing mobile code. After seeing renewed my MVP status, I was able to get my hands on a loaner developer Windows Phone 7 device. I have to personally thank Cristina Gonzales Herrero from Microsoft Spain for both (MVP and the phone).
Having a WP7 phone on my hands was just the excuse I needed to get back to mobile development. The first hurdle I had to overcome was the App Hub registration. My first attempt was to use my own company account to enroll but the registration process requires two people from the company. So what happens to companies of one like mine? Well, I turned back and took the individual path only to be greeted by payment form (yes, you have to pay USD $99 to deploy to the phone), that assumed I was a US citizen. After talking to some friends, I understood that the only way to go about this was to create a live.com.pt (I live in Portugal) account, but, before I could do that, I had to change my language preferences on IE. You see, I just cannot use a development machine with a Portuguese OS. The keyboard is OK, but not the OS "translations". I started developing on computers that could hardly "speak Portuguese" so I got used to the English language for development, and this also includes the language preferences on the browser. Incidentally, if you don't have Portuguese as your first browser language selection, you cannot create a live.com.pt account. Sigh! This should me much easier, Microsoft!
After going through all these hurdles, I managed to get my developer account and wrote my first mini-app: an XNA application that explores the device's accelerometer. It merely uses the accelerometer information to move a ball around the screen as you tilt the device (something that you have already seen). The accelerometer input in not treated in any special way so the movement you get is sluggish, just as if the ball is moving through molasses...
You can get the first sample from here.
The next version of the code will include more realistic ball movement, so there is some kinetics a dynamics stuff to review.
To help me in writing this tiny piece of code, I read the following articles:
Wednesday, January 19, 2011
Persisting Silverlight DataGrid sort descriptions
I came across this issue recently: how to persist Silverlight DataGrid sort descriptions between changes of the ItemsSource property? The DataGrid on version 4.0 does not expose a direct interface to manipulate the column sort descriptions although it somehow manages them internally. If you want to explicitly manage the column sort descriptions, you must use a PagedCollectionView container, through the SortDescriptions collection.
If you feed a PagedCollectionView to a DataGrid and then let the user change the column sort descriptions through the user interface (by clicking the column headers), the SortDescriptions collection will store the user changes. After realizing this, I devised a very simple strategy to persist the column sort descriptions whenever I needed to refresh the DataGrid:
To make my life a bit easier, I created a very simple helper class with two private members:
private DataGrid dataGrid = null;
private PagedCollectionView pagedView = null;
The constructor simply stores the target DataGrid object reference:
If you feed a PagedCollectionView to a DataGrid and then let the user change the column sort descriptions through the user interface (by clicking the column headers), the SortDescriptions collection will store the user changes. After realizing this, I devised a very simple strategy to persist the column sort descriptions whenever I needed to refresh the DataGrid:
- If the data source is a PagedViewCollection, I just make a copy of the old SortDescriptions collection and apply it to the new PagedViewCollection object.
- If the data source is just an IEnumerable, I create a new PagedViewCollection to wrap it and do the same as the previous point.
To make my life a bit easier, I created a very simple helper class with two private members:
private DataGrid dataGrid = null;
private PagedCollectionView pagedView = null;
The constructor simply stores the target DataGrid object reference:
public PersistDataGridSort(DataGrid dataGrid)
{
this.dataGrid = dataGrid;
}
The bulk of the work is done in the SetItemsSource function that takes an object as parameter. This must be either an IEnumerable or a PagedCollectionView:
public void SetItemsSource(object collection)
{
SortDescriptionCollection sortDescriptions = null;
if(collection is PagedCollectionView)
{
if(pagedView != null)
{
sortDescriptions = new SortDescriptionCollection();
foreach(SortDescription sortDescr in pagedView.SortDescriptions)
{
sortDescriptions.Add(sortDescr);
}
}
pagedView = collection as PagedCollectionView;
pagedView.SortDescriptions.Clear();
}
else if(collection is IEnumerable)
{
IEnumerable enumerable = collection as IEnumerable;
if(pagedView != null)
sortDescriptions = pagedView.SortDescriptions;
pagedView = new PagedCollectionView(enumerable);
}
else
throw new ArgumentException("Collection must be either a PagedCollectionView or an IEnumerable.");
// Set the data grid's source
dataGrid.ItemsSource = pagedView;
// Reinstate the old sort descriptions
if(sortDescriptions != null)
{
foreach(SortDescription sortDescr in sortDescriptions)
pagedView.SortDescriptions.Add(sortDescr);
}
}
To use this class, just create an instance using the target DataGrid and set its data source by calling this class' SetItemsSource method. Have fun!
Tuesday, November 30, 2010
FireFox, WCF callbacks and HtmlPage.Window.Alert
This seems to be a deadly mix: calling HtmlPage.Window.Alert on a WCF web service callback on FireFox. While you get the correct behavior in IE and Chrome, FireFox just hangs miserably. Beware...
Sunday, November 21, 2010
Templated Silverlight ListBox
Whenever you use a Silverlight ListBox element with templated items, it is a good idea to force the item content to stretch horizontally. This way each item’s content will occupy the full width of the ListBox, leaving no “dead” areas. I found this to be particularly useful when handling mouse event on the item container because on shorter items you would get an area to the right that is blind to the mouse events. The solution is quite simple (I found it elsewhere on the net, but post it here because I find it so useful):
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
Happy silverlighting!
Sunday, November 7, 2010
From DataTable to DataContract
For the last four months, I have been very busy porting a large SaaS application from the traditional ASP .NET + Ajax platform to Silverlight 4. This application has a quite standard architecture with a data access layer that talks to the database and exposes a simplified interface to the business level. When a piece of data is required, you just need to call a given method with the appropriate parameters and you usually get back a DataTable object with all the data you need. This is a very flexible scenario because you can directly bind to an ASP .NET control or, if you need to further massage the data, transform the data in memory before binding it.
This architecture became a bit of a problem when I started to port the application to Silverlight because it just does not understand ADO .NET, so it is useless to try to marshal a DataTable object through a WCF web service. Because we needed to keep the "old" ASP .NET application running, there was no point in rewriting the old DAL code so a decision was made to keep it and reuse it as a data source for the new WCF web services. This meant writing a lot of boring code to implement the new DataContract classes. When you create a Silverlight-enabled WCF web service, you must send and receive all your data through strongly-typed classes that are very neatly marshalled over between the two endpoints.
I tackled this issue by starting to write all the new DataContract code by hand... until I got bored. The process is incredibly boring, time-consuming and error-prone. After a few weeks at it, I found out that writing all the WCF plumbing was taking a large portion of every ported feature, so this needed a closer look. What could I do to help me bridge the gap between the existing, tried and true DataTables and the new DataContracts?
A code generator.
The idea is quite simple: plug in a piece of code that takes either the freshly-created DataTable (or DataView) and generates a text file containing C# code that declares two DataContracts: one for each row and another for the whole list of rows. Oddly, this code must run on your web server, so it is best suited for your development environment only. To make my life easy, I created a single extension method to the DataTable and DataView classes that you use like this:
dataTable.WriteListDataContract("SingleRowClassName", @"C:\Path", "ID");
The first parameter is the row class name: the extension will automatically generate the corresponding list class name by appending the "List" string to this class name. The second parameter contains the path of the generated file name (based on the first parameter). The last parameter is an optional string containing a comma seperated list of columns that you want to force as non-nullable (the code will throw an exception when trying to convert a DBNull.Value).
Once you have the generated code files, you can comment out the line.
Using the generated code is very straightforward: just paste it in your WCF source code file. Reuse your old DAL code and, when you have the DataTable or DataView ready, create a list class and call its Load method. The generated code reads in the data and converts it into a generic list that you can immediately return to your Silverlight application.
Here's the source code: DataTableExtensions.cs
This architecture became a bit of a problem when I started to port the application to Silverlight because it just does not understand ADO .NET, so it is useless to try to marshal a DataTable object through a WCF web service. Because we needed to keep the "old" ASP .NET application running, there was no point in rewriting the old DAL code so a decision was made to keep it and reuse it as a data source for the new WCF web services. This meant writing a lot of boring code to implement the new DataContract classes. When you create a Silverlight-enabled WCF web service, you must send and receive all your data through strongly-typed classes that are very neatly marshalled over between the two endpoints.
I tackled this issue by starting to write all the new DataContract code by hand... until I got bored. The process is incredibly boring, time-consuming and error-prone. After a few weeks at it, I found out that writing all the WCF plumbing was taking a large portion of every ported feature, so this needed a closer look. What could I do to help me bridge the gap between the existing, tried and true DataTables and the new DataContracts?
A code generator.
The idea is quite simple: plug in a piece of code that takes either the freshly-created DataTable (or DataView) and generates a text file containing C# code that declares two DataContracts: one for each row and another for the whole list of rows. Oddly, this code must run on your web server, so it is best suited for your development environment only. To make my life easy, I created a single extension method to the DataTable and DataView classes that you use like this:
dataTable.WriteListDataContract("SingleRowClassName", @"C:\Path", "ID");
The first parameter is the row class name: the extension will automatically generate the corresponding list class name by appending the "List" string to this class name. The second parameter contains the path of the generated file name (based on the first parameter). The last parameter is an optional string containing a comma seperated list of columns that you want to force as non-nullable (the code will throw an exception when trying to convert a DBNull.Value).
Once you have the generated code files, you can comment out the line.
Using the generated code is very straightforward: just paste it in your WCF source code file. Reuse your old DAL code and, when you have the DataTable or DataView ready, create a list class and call its Load method. The generated code reads in the data and converts it into a generic list that you can immediately return to your Silverlight application.
Here's the source code: DataTableExtensions.cs
Thursday, October 28, 2010
Google Maps V3 tip: fitBounds
Never call the fitBounds method on your Google Maps V3 map when the supporting div is hidden. This will result in an incorrectly calculated zoom level because (apparently) the JavaScript code cannot determine the div dimensions. Always make sure the div is visible before calling fitBounds.
Monday, October 25, 2010
A ReadyBoost tip
I own a relatively old laptop (a once-glorious ASUS Lamborghini VX2) which is limited to 2 GB of RAM. The box is now showing its age, especially when using VS 2010. (Not to mention the lack of a WDDM 1.1 driver for the NVidia Ge Force GO 7700, which makes developing for WP7 a horrible experience). To make things run smoother (or at least to try to make them run smoother), I removed all the “Visual experience” checkboxes in VS 2010 (under Tools / Options) and bought an 8 GB USB flash drive for ReadyBoost.
With the standard FAT formatted file system, ReadyBoost is limited to a 4 GB cache. It does make things a little better but barely worth the effort. Recently I read an MSDN article on this subject that stated that this limitation goes up to 32 GB if you format the flash drive using NTFS. After doing so, I got a 7.7 GB ReadyBoost cache (not the full 8 GB because the manufacturers measure capacity in a different but interesting way) and a noticeable improvement for my old box. Now VS 2010 does load a bit faster and the whole thing does feel a bit more agile.
No luck with the NVidia driver, though…
With the standard FAT formatted file system, ReadyBoost is limited to a 4 GB cache. It does make things a little better but barely worth the effort. Recently I read an MSDN article on this subject that stated that this limitation goes up to 32 GB if you format the flash drive using NTFS. After doing so, I got a 7.7 GB ReadyBoost cache (not the full 8 GB because the manufacturers measure capacity in a different but interesting way) and a noticeable improvement for my old box. Now VS 2010 does load a bit faster and the whole thing does feel a bit more agile.
No luck with the NVidia driver, though…
Wednesday, October 6, 2010
Silverlight 4, FireFox and Accented Characters
My mother gave me a very common portuguese name: João. You can translate it to 'John', 'Jean', 'Juan' (take your pick). The odd thing about my first name are the three consecutive vowels and the tilde character on top of the 'a'. I get all sorts of funny jokes from my anglo-saxon friends due to this personal oddity. Why is this relevant?
I have been working with Silverlight 4 for a web application (I'm essentally rewriting a big HTML SaaS application) and met a very strange behavior with Silverlight 4 when running on FireFox (and Chrome): I just could not write my name on a TextBox! This is a situation that has been reported by some users but, interestingly, it's not a very common complaint. Of course IE works OK with this.
When searching for a solution for this problem, I found a sample where this issue did not happen. After a bit of research I found the culprit: the "windowless" parameter on the HTML object element (my code had it while the sample did not). If you set this parameter to "true", FireFox will not compose the '~' and the 'a' to produce the dreaded 'ã', so beware!
This issue is irrelevant for english-speaking (and writing) users.
I have been working with Silverlight 4 for a web application (I'm essentally rewriting a big HTML SaaS application) and met a very strange behavior with Silverlight 4 when running on FireFox (and Chrome): I just could not write my name on a TextBox! This is a situation that has been reported by some users but, interestingly, it's not a very common complaint. Of course IE works OK with this.
When searching for a solution for this problem, I found a sample where this issue did not happen. After a bit of research I found the culprit: the "windowless" parameter on the HTML object element (my code had it while the sample did not). If you set this parameter to "true", FireFox will not compose the '~' and the 'a' to produce the dreaded 'ã', so beware!
This issue is irrelevant for english-speaking (and writing) users.
Monday, July 12, 2010
Windows Phone Developer Tools Beta
The Windows Phone Developer Tools Beta are now available for download from the Microsoft Download Center.
Wednesday, July 7, 2010
SQL Compact 4.0 CTP1 Released
Microsoft has just released SQL Compact 4.0 CTP1. You can download it from the Microsoft download center now.
Saturday, July 3, 2010
And now for something completely different...
After long months of having my laptop running way too hot (sometimes it would shut down to prevent something from melting inside), I decided to open it up and use the household vacuum cleaner around the cooler fan, air ducts and vents. The result? Around 10 degrees (C) cooler...
Monday, June 14, 2010
Enumerating SQL Compact Tables, Columns, Constraints and Indexes
Now that you know how to enumerate tables and columns, it's fairly easy to enumerate all the other schema elements: indexes, primary keys, unique constraints and foreign keys. Interstingly both primary keys and unique constraints are implemented as indexes and you list them all through the INFORMATION_SCHEMA.INDEXES view (I'm omitting the prefix from now on). This view will tell you immediately if an index is the table's primary key, but will not tell you if you are looking at an unique constraint. To check that, you must take a look at the TABLE_CONSTRAINTS view.
Foreign keys are a bit different: you must know what table they refer to (through a primary key, unique index or unique constraint), what columns are mapped and what are the update and delete rules. You get some of this information from the REFERENTIAL_CONSTRAINTS view, but you must complement it using the KEY_COLUMN_USAGE view.
You can see this mechanism at work on the sample code's updated SqlCeTable.LoadSchema method. Note that I kept the piece-wise loading mechanism in order to make things work faster. Alternatively you could devise an alternative schema loading mechanism using a DataSet to store all the data and then query it appropriately. Unfortunately this will imply a performance penalty if you port this code to a mobile device.
Now that we have a simple way to load and query the database schema, we can widen our horizons a bit and start extracting more useful information like scripts. Stay tuned for the next episodes...
Sample code: SchemaTree2.zip
Foreign keys are a bit different: you must know what table they refer to (through a primary key, unique index or unique constraint), what columns are mapped and what are the update and delete rules. You get some of this information from the REFERENTIAL_CONSTRAINTS view, but you must complement it using the KEY_COLUMN_USAGE view.
You can see this mechanism at work on the sample code's updated SqlCeTable.LoadSchema method. Note that I kept the piece-wise loading mechanism in order to make things work faster. Alternatively you could devise an alternative schema loading mechanism using a DataSet to store all the data and then query it appropriately. Unfortunately this will imply a performance penalty if you port this code to a mobile device.
Now that we have a simple way to load and query the database schema, we can widen our horizons a bit and start extracting more useful information like scripts. Stay tuned for the next episodes...
Sample code: SchemaTree2.zip
Friday, June 11, 2010
Windows Phone 7 Development Videos from TechEd 2010
Here are a couple of videos from TechEd 2010 North America on how to develop Silverlight applications for Windows Phone 7:
An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 1)
An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 2)
You can follow the full Windows Phone track here.
An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 1)
An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 2)
You can follow the full Windows Phone track here.
Subscribe to:
Posts (Atom)