<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2423328738091903368</id><updated>2012-02-17T00:55:52.202Z</updated><category term='Sensor'/><category term='Windows Mobile'/><category term='Windows Phone 7'/><category term='WTL'/><category term='ReadyBoost'/><category term='HTC'/><category term='WCF'/><category term='Google Maps V3'/><category term='Accelerometer'/><category term='Server'/><category term='DataGrid'/><category term='eVC3'/><category term='RAPI'/><category term='Client'/><category term='SQL Compact'/><category term='Silverlight'/><category term='FireFox'/><title type='text'>Smiling Smith</title><subtitle type='html'>Software development fragments and thoughts</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>27</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-6018498922584920637</id><published>2012-01-10T09:45:00.000Z</published><updated>2012-01-10T09:45:27.781Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Silverlight, Library Caching and blank screens</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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&amp;nbsp;&lt;a href="https://connect.microsoft.com/VisualStudio/feedback/details/689418/silverlight-forum-application-is-not-loaded-completely-sometimes-when-using-splash-screen-and-enable-applicaion-library-caching"&gt;reported issue&lt;/a&gt;, but as you can see it's solved because Microsoft cannot reproduce it.&lt;br /&gt;&lt;br /&gt;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?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-6018498922584920637?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/6018498922584920637/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2012/01/silverlight-library-caching-and-blank.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6018498922584920637'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6018498922584920637'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2012/01/silverlight-library-caching-and-blank.html' title='Silverlight, Library Caching and blank screens'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-2790324650379002567</id><published>2011-02-12T22:24:00.000Z</published><updated>2011-02-12T22:24:56.708Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Accelerometer'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Phone 7'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>The skewed accelerometer</title><content type='html'>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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;You can get the sample application with source code &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/AccelerometerTool.zip"&gt;here&lt;/a&gt;. 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.&lt;br /&gt;&lt;br /&gt;Now I can get back to my XNA gravity ball code and make it work like it should.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-2790324650379002567?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/2790324650379002567/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/skewed-accelerometer.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2790324650379002567'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2790324650379002567'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/skewed-accelerometer.html' title='The skewed accelerometer'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-3181830786910536364</id><published>2011-02-11T14:12:00.000Z</published><updated>2011-02-11T14:12:25.531Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>MediaElement and downloaded sound</title><content type='html'>In a nutshell: when you download a sound file to play on a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MediaElement&lt;/span&gt;, make sure you set the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;AutoPlay&lt;/span&gt; property to &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;True&lt;/span&gt; if you call &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SetSource&lt;/span&gt; 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 &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;MemoryStream&lt;/span&gt; (it supports seeks). I found this out the hard way...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-3181830786910536364?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/3181830786910536364/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/mediaelement-and-downloaded-sound.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3181830786910536364'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3181830786910536364'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/mediaelement-and-downloaded-sound.html' title='MediaElement and downloaded sound'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-6485841366598630186</id><published>2011-02-08T22:49:00.000Z</published><updated>2011-02-08T22:49:14.961Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google Maps V3'/><title type='text'>The Tabukiniberu bug</title><content type='html'>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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;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&amp;nbsp;European&amp;nbsp;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 &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;fitBounds&lt;/span&gt; on an empty &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;LatLngBounds&lt;/span&gt; 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...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-6485841366598630186?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/6485841366598630186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/tabukiniberu-bug.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6485841366598630186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6485841366598630186'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2011/02/tabukiniberu-bug.html' title='The Tabukiniberu bug'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-2029429419302833284</id><published>2011-01-31T09:43:00.000Z</published><updated>2011-01-31T09:43:41.948Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Accelerometer'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Phone 7'/><title type='text'>Back to mobile!</title><content type='html'>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 &amp;nbsp;(MVP and the phone).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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&amp;nbsp;Portuguese" so I got used to the&amp;nbsp;English&amp;nbsp;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!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;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...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can get the first sample from &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/GravityBall1.zip"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The next version of the code will include more realistic ball movement, so there is some&amp;nbsp;kinetics&amp;nbsp;a dynamics stuff to review.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To help me in writing this tiny piece of code, I read the following articles:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://windowsteamblog.com/windows_phone/b/wpdev/archive/2010/09/08/using-the-accelerometer-on-windows-phone-7.aspx"&gt;Using the Accelerometer on Windows Phone 7&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://blogs.msdn.com/b/shawnhar/archive/2010/07/12/orientation-and-rotation-on-windows-phone.aspx"&gt;Orientation and rotation on Windows Phone&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-2029429419302833284?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/2029429419302833284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2011/01/back-to-mobile.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2029429419302833284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2029429419302833284'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2011/01/back-to-mobile.html' title='Back to mobile!'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-6085032539187473400</id><published>2011-01-19T09:27:00.000Z</published><updated>2011-01-19T09:27:12.009Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='DataGrid'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Persisting Silverlight DataGrid sort descriptions</title><content type='html'>I came across this issue recently: how to persist Silverlight &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt; sort descriptions between changes of the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;ItemsSource&lt;/span&gt; property? The &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt; 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 &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedCollectionView&lt;/span&gt; container, through the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SortDescriptions&lt;/span&gt; collection.&lt;br /&gt;&lt;br /&gt;If you feed a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedCollectionView&lt;/span&gt; to a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt; and then let the user change the column sort descriptions through the user interface (by clicking the column headers), the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SortDescriptions&lt;/span&gt; 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 &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If the data source is a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedViewCollection&lt;/span&gt;, I just make a copy of the old &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SortDescriptions&lt;/span&gt; collection and apply it to the new &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedViewCollection&lt;/span&gt; object.&lt;/li&gt;&lt;li&gt;If the data source is just an &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IEnumerable&lt;/span&gt;, I create a new &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedViewCollection&lt;/span&gt; to wrap it and do the same as the previous point.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;To make my life a bit easier, I created a very simple helper class with two private members:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;private DataGrid&amp;nbsp;dataGrid&amp;nbsp;= null;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;private PagedCollectionView&amp;nbsp;pagedView&amp;nbsp;= null;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The constructor simply stores the target &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt; object reference:&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public PersistDataGridSort(DataGrid dataGrid)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;this.dataGrid = dataGrid;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The bulk of the work is done in the &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SetItemsSource&lt;/span&gt; function that takes an &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;object&lt;/span&gt; as parameter. This must be either an &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;IEnumerable&lt;/span&gt; or a &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;PagedCollectionView&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;public void SetItemsSource(object collection)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;SortDescriptionCollection sortDescriptions = null;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(collection is PagedCollectionView)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if(pagedView != null)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sortDescriptions = new SortDescriptionCollection();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;foreach(SortDescription sortDescr in pagedView.SortDescriptions)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sortDescriptions.Add(sortDescr);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pagedView = collection as PagedCollectionView;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pagedView.SortDescriptions.Clear();&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;else if(collection is IEnumerable)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;IEnumerable enumerable = collection as IEnumerable;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;if(pagedView != null)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;sortDescriptions = pagedView.SortDescriptions;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pagedView = new PagedCollectionView(enumerable);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;else&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;throw new ArgumentException("Collection must be either a PagedCollectionView or an IEnumerable.");&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Set the data grid's source&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;dataGrid.ItemsSource = pagedView;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// Reinstate the old sort descriptions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;if(sortDescriptions != null)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;{&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;foreach(SortDescription sortDescr in sortDescriptions)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;pagedView.SortDescriptions.Add(sortDescr);&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;}&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;To use this class, just create an instance using the target &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;DataGrid&lt;/span&gt; and set its data source by calling this class' &lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;SetItemsSource&lt;/span&gt; method. Have fun!&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-6085032539187473400?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/6085032539187473400/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2011/01/persisting-silverlight-datagrid-sort.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6085032539187473400'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6085032539187473400'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2011/01/persisting-silverlight-datagrid-sort.html' title='Persisting Silverlight DataGrid sort descriptions'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-419131572219155060</id><published>2010-11-30T13:52:00.000Z</published><updated>2010-11-30T13:52:53.522Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='FireFox'/><title type='text'>FireFox, WCF callbacks and HtmlPage.Window.Alert</title><content type='html'>This seems to be a deadly mix: calling &lt;span style="color: #2b91af; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #2b91af; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: #2b91af; font-family: Consolas; font-size: x-small;"&gt;HtmlPage&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas; font-size: x-small;"&gt;&lt;span style="font-family: Consolas; font-size: x-small;"&gt;.Window.Alert &lt;/span&gt;&lt;/span&gt;on a WCF web service callback on FireFox. While you get the correct behavior in IE and Chrome, FireFox just hangs miserably. Beware...&lt;span style="color: green; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: green; font-family: Consolas; font-size: x-small;"&gt;&lt;span style="color: green; font-family: Consolas; font-size: x-small;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-419131572219155060?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/419131572219155060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/firefox-wcf-callbacks-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/419131572219155060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/419131572219155060'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/firefox-wcf-callbacks-and.html' title='FireFox, WCF callbacks and HtmlPage.Window.Alert'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-2542070727627553472</id><published>2010-11-21T19:15:00.001Z</published><updated>2010-11-21T19:15:28.727Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Templated Silverlight ListBox</title><content type='html'>&lt;p&gt;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):&lt;/p&gt;  &lt;p&gt;&lt;font face="Courier New"&gt;&amp;lt;ListBox.ItemContainerStyle&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Style TargetType=&amp;quot;ListBoxItem&amp;quot;&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;Setter Property=&amp;quot;HorizontalContentAlignment&amp;quot; Value=&amp;quot;Stretch&amp;quot; /&amp;gt;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/Style&amp;gt;      &lt;br /&gt;&amp;lt;/ListBox.ItemContainerStyle&amp;gt;&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Happy silverlighting!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-2542070727627553472?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/2542070727627553472/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/templated-silverlight-listbox.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2542070727627553472'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2542070727627553472'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/templated-silverlight-listbox.html' title='Templated Silverlight ListBox'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-2773647215043322727</id><published>2010-11-07T19:34:00.001Z</published><updated>2010-11-07T19:35:15.722Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>From DataTable to DataContract</title><content type='html'>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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt; 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&amp;nbsp;binding it.&lt;br /&gt;&lt;br /&gt;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt; 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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataContract&lt;/span&gt; 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.&lt;br /&gt;&lt;br /&gt;I tackled this issue by starting to write all the new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataContract&lt;/span&gt; code by hand... until I got bored. The process is incredibly boring, time-consuming&amp;nbsp;and error-prone. After a few weeks at it, I found out that writing all the WCF plumbing was&amp;nbsp;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt;s and the new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataContract&lt;/span&gt;s?&lt;br /&gt;&lt;br /&gt;A code generator.&lt;br /&gt;&lt;br /&gt;The idea is quite simple: plug in a piece of code that takes either the freshly-created &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt; (or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataView&lt;/span&gt;) and generates a text file containing &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;C#&lt;/span&gt; code that declares two &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataContract&lt;/span&gt;s: 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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataView&lt;/span&gt; classes that you use like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-family: Consolas;"&gt;dataTable.WriteListDataContract(&lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;"SingleRowClassName"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-family: Consolas;"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;@"C:\Path"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-family: Consolas;"&gt;, &lt;/span&gt;&lt;/span&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;&lt;span style="color: #a31515; font-family: Consolas;"&gt;"ID"&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-family: Consolas;"&gt;&lt;span style="font-family: Consolas;"&gt;);&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DBNull.Value&lt;/span&gt;).&lt;br /&gt;&lt;br /&gt;Once you have the generated code files, you can comment out the line.&lt;br /&gt;&lt;br /&gt;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataTable&lt;/span&gt; or &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataView&lt;/span&gt; ready, create a list class and call its &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Load&lt;/span&gt; method. The generated code reads in the data and converts it into a generic list that you can immediately return to your Silverlight application.&lt;br /&gt;&lt;br /&gt;Here's the source code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/DataTableExtensions.cs"&gt;DataTableExtensions.cs&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-2773647215043322727?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/2773647215043322727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/from-datatable-to-datacontract.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2773647215043322727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2773647215043322727'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/11/from-datatable-to-datacontract.html' title='From DataTable to DataContract'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-6619334025519436987</id><published>2010-10-28T10:17:00.003+01:00</published><updated>2010-10-28T11:18:02.751+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Google Maps V3'/><title type='text'>Google Maps V3 tip: fitBounds</title><content type='html'>Never call the &lt;strong&gt;fitBounds&lt;/strong&gt; method on your Google Maps V3 map when the supporting &lt;strong&gt;div&lt;/strong&gt; is hidden. This will result in an incorrectly calculated zoom level because (apparently) the JavaScript code cannot determine the &lt;strong&gt;div&lt;/strong&gt; dimensions. Always make sure the &lt;strong&gt;div&lt;/strong&gt; is visible before calling &lt;strong&gt;fitBounds&lt;/strong&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-6619334025519436987?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/6619334025519436987/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/google-maps-v3-tip-fitbounds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6619334025519436987'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6619334025519436987'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/google-maps-v3-tip-fitbounds.html' title='Google Maps V3 tip: fitBounds'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-8142697914165978391</id><published>2010-10-25T13:43:00.002+01:00</published><updated>2010-10-25T13:44:43.649+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ReadyBoost'/><title type='text'>A ReadyBoost tip</title><content type='html'>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.&lt;br /&gt;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.&lt;br /&gt;No luck with the NVidia driver, though…&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-8142697914165978391?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/8142697914165978391/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/readyboost-tip.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/8142697914165978391'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/8142697914165978391'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/readyboost-tip.html' title='A ReadyBoost tip'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-7703980087266630936</id><published>2010-10-06T18:17:00.000+01:00</published><updated>2010-10-06T18:17:00.984+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Silverlight 4, FireFox and Accented Characters</title><content type='html'>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?&lt;br /&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;When searching for a solution for this problem,&amp;nbsp;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&amp;nbsp;'ã', so beware!&lt;br /&gt;&lt;br /&gt;This issue is irrelevant for english-speaking (and writing) users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-7703980087266630936?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/7703980087266630936/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/silverlight-4-firefox-and-accented.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7703980087266630936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7703980087266630936'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/10/silverlight-4-firefox-and-accented.html' title='Silverlight 4, FireFox and Accented Characters'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-3330091594061770383</id><published>2010-07-12T21:03:00.000+01:00</published><updated>2010-07-12T21:03:43.604+01:00</updated><title type='text'>Windows Phone Developer Tools Beta</title><content type='html'>The Windows Phone Developer Tools Beta are now available for download from the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=c8496c2a-54d9-4b11-9491-a1bfaf32f2e3&amp;amp;displaylang=en"&gt;Microsoft Download Center&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-3330091594061770383?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/3330091594061770383/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/windows-phone-developer-tools-beta.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3330091594061770383'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3330091594061770383'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/windows-phone-developer-tools-beta.html' title='Windows Phone Developer Tools Beta'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-5257899073493221752</id><published>2010-07-07T14:08:00.001+01:00</published><updated>2010-07-07T14:08:31.596+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Compact'/><title type='text'>SQL Compact 4.0 CTP1 Released</title><content type='html'>Microsoft has just released SQL Compact 4.0 CTP1. You can download it from the &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=0d2357ea-324f-46fd-88fc-7364c80e4fdb&amp;amp;displaylang=en"&gt;Microsoft download center&lt;/a&gt; now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-5257899073493221752?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/5257899073493221752/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/sql-compact-40-ctp1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/5257899073493221752'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/5257899073493221752'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/sql-compact-40-ctp1.html' title='SQL Compact 4.0 CTP1 Released'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-2436530529930351825</id><published>2010-07-03T15:52:00.000+01:00</published><updated>2010-07-03T15:52:46.745+01:00</updated><title type='text'>And now for something completely different...</title><content type='html'>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...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-2436530529930351825?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/2436530529930351825/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/and-now-for-something-completely.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2436530529930351825'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/2436530529930351825'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/07/and-now-for-something-completely.html' title='And now for something completely different...'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-7270560149998028841</id><published>2010-06-14T21:36:00.002+01:00</published><updated>2010-06-14T21:37:19.211+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Compact'/><title type='text'>Enumerating SQL Compact Tables, Columns, Constraints and Indexes</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_AksH5-lumMs/TBaPUGfLDSI/AAAAAAAAAeY/EQZKce5jfhs/s1600/DbSchema1.PNG" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" qu="true" src="http://4.bp.blogspot.com/_AksH5-lumMs/TBaPUGfLDSI/AAAAAAAAAeY/EQZKce5jfhs/s320/DbSchema1.PNG" /&gt;&lt;/a&gt;&lt;/div&gt;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;INFORMATION_SCHEMA.INDEXES&lt;/span&gt; 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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;TABLE_CONSTRAINTS&lt;/span&gt; view.&lt;br /&gt;&lt;br /&gt;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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;REFERENTIAL_CONSTRAINTS&lt;/span&gt; view, but you must complement it using the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;KEY_COLUMN_USAGE&lt;/span&gt; view.&lt;br /&gt;&lt;br /&gt;You can see this mechanism at work on the sample code's updated &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeTable.LoadSchema&lt;/span&gt; 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 &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;DataSet&lt;/span&gt; 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.&lt;br /&gt;&lt;br /&gt;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...&lt;br /&gt;&lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/SchemaTree2.zip"&gt;SchemaTree2.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-7270560149998028841?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/7270560149998028841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/enumerating-sql-compact-tables-columns.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7270560149998028841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7270560149998028841'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/enumerating-sql-compact-tables-columns.html' title='Enumerating SQL Compact Tables, Columns, Constraints and Indexes'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_AksH5-lumMs/TBaPUGfLDSI/AAAAAAAAAeY/EQZKce5jfhs/s72-c/DbSchema1.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-4230376007746942510</id><published>2010-06-11T12:06:00.001+01:00</published><updated>2010-06-11T12:11:35.371+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows Phone 7'/><category scheme='http://www.blogger.com/atom/ns#' term='Silverlight'/><title type='text'>Windows Phone 7 Development Videos from TechEd 2010</title><content type='html'>Here are a couple of videos from TechEd 2010 North America&amp;nbsp;on how to develop Silverlight applications for Windows Phone 7:&lt;br /&gt;&lt;a href="http://www.msteched.com/2010/NorthAmerica/WPH304"&gt;An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 1)&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.msteched.com/2010/NorthAmerica/WPH305"&gt;An In-Depth View of Building Applications for Windows Phone 7 with Microsoft Silverlight (Part 2)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;You can follow the full Windows Phone track &lt;a href="http://www.msteched.com/Tracks/WindowsPhone"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-4230376007746942510?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/4230376007746942510/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/windows-phone-7-development-videos-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/4230376007746942510'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/4230376007746942510'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/windows-phone-7-development-videos-from.html' title='Windows Phone 7 Development Videos from TechEd 2010'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-6162055596747413149</id><published>2010-06-10T11:47:00.000+01:00</published><updated>2010-06-10T11:47:39.529+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Compact'/><title type='text'>Enumerating SQL Compact Tables and Columns</title><content type='html'>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/_AksH5-lumMs/TBC-u5eDzLI/AAAAAAAAAeQ/_1Khzw4OlSk/s1600/DbSchema0.PNG" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" qu="true" src="http://1.bp.blogspot.com/_AksH5-lumMs/TBC-u5eDzLI/AAAAAAAAAeQ/_1Khzw4OlSk/s320/DbSchema0.PNG" width="184" /&gt;&lt;/a&gt;&lt;/div&gt;Today I'm starting a small series of blog posts where I will show how you can&amp;nbsp;enumerate&amp;nbsp;a SQL Compact database schema using the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;INFORMATION_SCHEMA&lt;/span&gt; views. Let's start with the basic stuff: tables and columns.&lt;br /&gt;&lt;br /&gt;Table enumeration is performed by querying the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;TABLES&lt;/span&gt; view, most specifically the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;TABLE_NAME&lt;/span&gt; column. I implemented the new &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeSchema&lt;/span&gt; class&amp;nbsp;(see sample code) that you can use for this purpose. Instances of this class are created with a reference to a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeConnection&lt;/span&gt; object and you populate the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Tables&lt;/span&gt; collection by calling the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Load&lt;/span&gt; method (make sure the connection is open). Note that this operation merely loads the table names and creates empty &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeTable&lt;/span&gt; objects. To retrieve the column information for each table, you must call the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeTable.LoadSchema&lt;/span&gt; method.&lt;br /&gt;&lt;br /&gt;I designed the code this way in order to avoid long loading times for&amp;nbsp;large databases. This way you can load only the schema for a particular table without the need to load the entire database schema.&lt;br /&gt;&lt;br /&gt;You can see this at work in the sample code: it displays a simple tree containing the list of tables in a given database and the column enumeration is requested per table when you expand the table node.&lt;br /&gt;&lt;br /&gt;Right now the code is limited to table and some of the column schema. I will be updating this sample in future posts to include more column schama details, indexes and constraints.&lt;br /&gt;&lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/SchemaTree1.zip"&gt;SchemaTree1.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-6162055596747413149?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/6162055596747413149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/enumerating-sql-compact-tables-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6162055596747413149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/6162055596747413149'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/06/enumerating-sql-compact-tables-and.html' title='Enumerating SQL Compact Tables and Columns'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_AksH5-lumMs/TBC-u5eDzLI/AAAAAAAAAeQ/_1Khzw4OlSk/s72-c/DbSchema0.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-7506400256061307797</id><published>2010-05-31T22:48:00.001+01:00</published><updated>2010-05-31T22:48:15.044+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Compact'/><title type='text'>SQL Compact Table Export</title><content type='html'>This is a very simple variation on my last blog post: instead of copying the table to the same database, you can now copy it to another database (although with the same table&amp;nbsp;name, but you can easily change that). The table data is exported in the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Export&lt;/span&gt; method of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeTableTool&lt;/span&gt; class using a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeDataReader&lt;/span&gt; for reading and a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SqlCeResultSet&lt;/span&gt; for writing. Simple stuff, really...&lt;br /&gt;&lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/CopyTableSample2.zip"&gt;CopyTableSample2.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-7506400256061307797?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/7506400256061307797/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/sql-compact-table-export.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7506400256061307797'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7506400256061307797'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/sql-compact-table-export.html' title='SQL Compact Table Export'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-152664067296474847</id><published>2010-05-30T13:08:00.000+01:00</published><updated>2010-05-30T13:08:14.852+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SQL Compact'/><title type='text'>SQL Compact Table Copy</title><content type='html'>How do you make a copy of a SQL Compact table? Version 3.5 does not support the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SELECT INTO&lt;/span&gt; command that allows you to easily do just that. Instead, it provides the INSERT INTO SELECT FROM command that allows you to copy existing table data into another existing table. So we are only missing one part: how to create a replica of the existing table structure.&lt;br /&gt;&lt;br /&gt;If you want to stick to managed code only, you can read all the database structure information from the &lt;a href="http://msdn.microsoft.com/en-us/library/ms174156.aspx"&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;INFORMATION_SCHEMA&lt;/span&gt; views&lt;/a&gt;. To get information ot of these views, you just have to issue a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SELECT&lt;/span&gt; command. For instance:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SELECT * FROM INFORMATION_SCHEMA.TABLES&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;returns all the existing tables in the database. In our case, we need to get information from an existing table and build a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CREATE TABLE&lt;/span&gt; command out of it in order to create a replica of the original table. For this purpose, you can issue the following SQL command:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='TableName' ORDER BY ORDINAL_POSITION&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With a little work you can read from this data and build a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CREATE TABLE&lt;/span&gt; command. If you look at the returned data, you will see that you have all the information you need. In fact, you just need to set up a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;StringBuilder&lt;/span&gt; in your code, and start adding the columns and their types. You can fin this in the sample code (see below), although the code still does not support the numeric data type.&lt;br /&gt;&lt;br /&gt;After creating the table, you can now copy the data, making sure that you execute a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;SET IDENTITY_INSERT&lt;/span&gt; command on the target table if it has an identity column.&lt;br /&gt;&lt;br /&gt;The sample code has a very simple UI that allows you to specify a connection string, the original and target table names and a button to perform the copy.&lt;br /&gt;&lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/CopyTableSample.zip"&gt;CopyTableSample.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-152664067296474847?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/152664067296474847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/sql-compact-table-copy.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/152664067296474847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/152664067296474847'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/sql-compact-table-copy.html' title='SQL Compact Table Copy'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-1743535615224222736</id><published>2010-05-18T09:41:00.000+01:00</published><updated>2010-05-18T09:41:21.042+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sensor'/><category scheme='http://www.blogger.com/atom/ns#' term='RAPI'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Mobile'/><title type='text'>The Remote HTC G Sensor Client Application</title><content type='html'>Without further ado, here's the final version of the &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/HTCRemoteSensor.zip"&gt;desktop HTC G Sensor client&lt;/a&gt;. This very simple .NET 3.5 forms application reads the stream of data from the HTC G Sensor via RAPI and displays it on the screen. Obviously, you can adapt this to meet your particular needs.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_AksH5-lumMs/S_JRlP0ZxoI/AAAAAAAAAeI/rplqxF8GCyw/s1600/HTCGSensor.PNG" imageanchor="1" style="clear: left; cssfloat: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_AksH5-lumMs/S_JRlP0ZxoI/AAAAAAAAAeI/rplqxF8GCyw/s320/HTCGSensor.PNG" wt="true" /&gt;&lt;/a&gt;&lt;/div&gt;The main project in on the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGConsumer&lt;/span&gt; folder. Before trying to use this sample application, please make sure that the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCClient.dll&lt;/span&gt; file is on your output directory, otherwise you will get an exception. This is the desktop client DLL that connects to the device via RAPI and is consumed by the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTC.GSensor.dll&lt;/span&gt; assembly through the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTC.GSensor.RemoteClient&lt;/span&gt; class.&lt;br /&gt;&lt;br /&gt;Finally, don't forget to remove the RAPI restrictions on your device if you are running a WM6.x device. Enjoy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-1743535615224222736?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/1743535615224222736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/remote-htc-g-sensor-client-application.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/1743535615224222736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/1743535615224222736'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/remote-htc-g-sensor-client-application.html' title='The Remote HTC G Sensor Client Application'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_AksH5-lumMs/S_JRlP0ZxoI/AAAAAAAAAeI/rplqxF8GCyw/s72-c/HTCGSensor.PNG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-8219244526903956385</id><published>2010-05-14T14:45:00.001+01:00</published><updated>2010-05-14T14:46:00.365+01:00</updated><title type='text'>RAPI2 article on CodeProject</title><content type='html'>Thanks to &lt;a href="http://msmvps.com/blogs/albertosilva/default.aspx"&gt;Alberto&lt;/a&gt;'s head-up, here's an interesting article on RAPI and its lesser-known COM interface: &lt;a href="http://www.codeproject.com/KB/windows/CeDir.aspx"&gt;RAPI2: The Friend You Never Knew You Had&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-8219244526903956385?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/8219244526903956385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/rapi2-article-on-codeproject.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/8219244526903956385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/8219244526903956385'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/rapi2-article-on-codeproject.html' title='RAPI2 article on CodeProject'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-1067020175990635089</id><published>2010-05-09T18:48:00.001+01:00</published><updated>2010-05-09T18:50:28.426+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='eVC3'/><title type='text'>Flashback</title><content type='html'>&lt;em&gt;"I'll buy it if it works on my Pocket PC with a MIPS CPU..."&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;This was the rough message that a potential customer of my products wrote in a recent email. This is not unusual - some of my customers use the products because they still work with SQL CE 2.0. Apparently for business customers, a ten year old technology seems quite fitting for their daily work.&lt;br /&gt;&lt;br /&gt;The device component that ships with my products goes all the way back to Pocket PC 2002, when Microsoft decided to support only ARM-based CPUs and drop support for MIPS and other brands. I remember that this was a bit of a nuisance back then because there were some non-ARM devices on the market that suddenly lost the ability to upgrade to version 2002 (something similar is happening now, isn't it?).&lt;br /&gt;&lt;br /&gt;What this all means is that this particular person wants me to build the device DLL using the Pocket PC 2000 SDK. To my big disgrace, I found that my VMs were not properly configured so I set out to install a fresh XP VM with the Embedded Visual Tools 3.0 (2002 edition) plus the Pocket PC 2000 SDK. Fortunately, I kept copies of these museum-grade pieces of software because you cannot find them anymore from official Microsoft sources (namely MSDN).&lt;br /&gt;&lt;br /&gt;So I started to install the thing and was prompted to enter the product key. Where did I save it? Damn... Nowhere to be found! I do have the eVC4.0 one, but not the one for version 3.0. Or do I? Actually, if you are going down memory lane like I did this afternoon, remember that the key for eVC3.0 is the same as for eVC4.0 (someone told me long ago that the product would validate any key, but I did not try that). So look for a valid download souce for eVC4.0 (like CNET) and use the key they provide.&lt;br /&gt;&lt;br /&gt;Now that all is set up, let's enter the time machine...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-1067020175990635089?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/1067020175990635089/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/flashback.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/1067020175990635089'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/1067020175990635089'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/flashback.html' title='Flashback'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-9204010779157507901</id><published>2010-05-08T18:02:00.000+01:00</published><updated>2010-05-08T18:02:53.018+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Client'/><category scheme='http://www.blogger.com/atom/ns#' term='Sensor'/><category scheme='http://www.blogger.com/atom/ns#' term='RAPI'/><category scheme='http://www.blogger.com/atom/ns#' term='HTC'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Mobile'/><title type='text'>The HTC G Sensor RAPI Client</title><content type='html'>Now that we have a device RAPI extension DLL to capture the HTC G Sensor data it's time to write the PC client DLL. I wrote this as a native code DLL because it made my life simpler when interfacing with RAPI. It exposes five C-style functions that can be readily P/Invoked from .NET:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor_New&lt;/span&gt; - Creates a new native client object&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor_Delete&lt;/span&gt; - Destroys the native client object&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor_Open&lt;/span&gt; - Opens the remote HTC G Sensor server&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor_Close&lt;/span&gt; - Closes the remote HTC G Sensor server&lt;/li&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor_Read&lt;/span&gt; - Reads the HTC G Sensor data&lt;/li&gt;&lt;/ul&gt;The last three should be familiar to you right now, but why do we need the first two? Believe me that I learned this one quite painfully: when exposing native objects to managed code, always provide their memory management functions. The reason is quite simple: if you are allocating the native objects from the native C++ heap, you must delete them using the C++ memory management library. That's why you see a "new" and a "delete".&lt;br /&gt;&lt;br /&gt;So what do these functions look like? They are actually very simple:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;HTCGCLIENT_API void* HTCGSensor_New()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTCGSensorClient* pClient = new HTCGSensorClient();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return pClient;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Why the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;void*&lt;/span&gt; return type? These exported functions are meant to be used by the P/Invoke mechanism that should know nothing about the pointer type: it will be mapped to an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;IntPtr&lt;/span&gt; type and treated as an opaque data type. Likewise, there's no need to check the data type on input: &lt;br /&gt;&amp;nbsp; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;HTCGCLIENT_API int HTCGSensor_Open(void* pClient)&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;{&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HTCGSensorClient* client = (HTCGSensorClient*)pClient;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(client)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return client-&amp;gt;Open();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return E_FAIL;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace; font-size: x-small;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So these functions are there to act as&amp;nbsp;conduits between the a C++ object of type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorClient&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;,&lt;/span&gt; where the bulk of the work is done, and the calling .NET assembly. It should come as no surprise that this class also implements the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Open&lt;/span&gt;, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Close&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Read&lt;/span&gt; methods, besides the standard constructor and destructor. Things get a bit more interesting here because we must open a connection to the device server through RAPI (the sample code uses an updated version of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CRemoteAPI&lt;/span&gt; class that I &lt;a href="http://nativemobile.blogspot.com/2005/09/supporting-activesync-40.html"&gt;published ages ago&lt;/a&gt;). In a nutshell, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Open&lt;/span&gt; function (see the sample code) initializes RAPI and remotely invokes the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorStream&lt;/span&gt; function on the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGServer.dll&lt;/span&gt; file (by default it should be placed on the device's&amp;nbsp;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;\Windows&lt;/span&gt; folder, but you might want to change this). Note that a reference to a client-side version of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;IRAPIStream&lt;/span&gt; object is kept and that's how the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Read&lt;/span&gt; function gets the G sensor data. This function is implemented in terms of a write and a read operation. The write tells the server to fetch the G sensor data and then waits on the read for the data to arrive (that's why this might prove slow for high-frequency sampling: for each sample there must be a round-trip to the server). The data is copied to an &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorData&lt;/span&gt; variable passed in by pointer reference. Closing the client implies writing a command to the server and closing the RAPI connection. &lt;br /&gt;&amp;nbsp; &lt;br /&gt;On my next post I will wrap this small project up by publishing the high-level .NET assemblies that consume the HTC G Sensor data. &lt;br /&gt;&amp;nbsp; &lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/HTCGClient.zip"&gt;HTCGClient.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-9204010779157507901?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/9204010779157507901/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/htc-g-sensor-rapi-client.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/9204010779157507901'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/9204010779157507901'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/htc-g-sensor-rapi-client.html' title='The HTC G Sensor RAPI Client'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-3576110974209860983</id><published>2010-05-04T23:00:00.000+01:00</published><updated>2010-05-04T23:00:28.392+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Server'/><category scheme='http://www.blogger.com/atom/ns#' term='Sensor'/><category scheme='http://www.blogger.com/atom/ns#' term='RAPI'/><category scheme='http://www.blogger.com/atom/ns#' term='HTC'/><title type='text'>The HTC G Sensor RAPI Server</title><content type='html'>RAPI is one of the most useful features in the Windows CE OS because it allows you to remotely access your device while connected via ActiveSync or WMDC. It's like having a generic socket server on your device that is always listening for a connection from the connected PC and that, besides implementing a nuber of very useful APIs (Registry and File System to name a few) it also allows you to extend it by using special DLLs. Unfortunately this feature also is a security issue because it allows any connected PC to scan your device's file for instance. This issue was solved with the Windows Mobile 5 version of the OS by enforcing security policies that vary in degree of strictness. For Smatphones, the security policy has always been much stricter than for "Pocket PCs" (the main distinction between both is whether or not the screen is touch-sensitive), with their "two-tiered" security model. Pocket PCs have a single-tier security model and are a bit kinder on security. In a nutshell, you usually get these devices either partially or totally locked for RAPI connections. If your device is completely locked, then there's no hope for you and you can stop reading this right now. On the other hand, if you have a partially locked device you can either use VS2008's Device Secutity Manager tool to crack open the device's security or use the SDK cerificates to sign your DLL (you don't want to spend money on this by purchasing Geotrust signing events, do you?). Anyway, if you plan to sell your DLL as part of an application's setup file, you will have to sign it (and do some other crazy stuff like marking the DLL file with the system attribute bit and adding a bit of XML to the cab).&lt;br /&gt;&lt;br /&gt;Writing the DLL is way simpler than all of the above. Open VS2008 and create a new project and select&amp;nbsp;Visual C++ / Smart Device / Win32 Smart Device Project. Name this project "HTCGServer". When the Win32 Smart Device Project Wizard shows up, click the Next button to select the desired SDKs. Next, select the "DLL" radio button and the "Export symbols" check box.&lt;br /&gt;&lt;br /&gt;Because this is a RAPI extension library, we need to make a reference to the RAPI header files which ship &lt;br /&gt;with the SDKs. On my system the header file is on this folder:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;C:\Program Files\Windows CE Tools\wce500\Windows Mobile 5.0 Pocket PC SDK\Activesync\Inc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;For the Windows Mobile 6.0 SDK, you can find the same files here:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;C:\Program Files\Windows Mobile 6 SDK\Activesync\inc&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Go to your project's properties and select the "C/C++" option on the left tree and add one of the above paths (please validate these paths against your system first) to the "Additional Include Directories" property. This is where you add paths for header files other than the ones that ship with the SDK and that are not in your project's source path. Make sure that both the "Release" and "Debug" configurations have these paths set before you go on.&lt;br /&gt;&lt;br /&gt;Now, let's take a look at the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGServer.h&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGServer.cpp&lt;/span&gt; fils that the Project Wizard created for us. Both files contain samples of DLL exportable symbols: a variable, a function and a class. All of them are marked with the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSERVER_API&lt;/span&gt; macro that is defined at the top of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGServer.h&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#ifdef HTCGSERVER_EXPORTS&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#define HTCGSERVER_API __declspec(dllexport)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#define HTCGSERVER_API __declspec(dllimport)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This works in a very simlple way: when you compile this header file from within the DLL project, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSERVER_EXPORTS&lt;/span&gt; macro is defined, so &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSERVER_API&lt;/span&gt; resolves to &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;__declspec(dllexport)&lt;/span&gt;, meaning that you want to export this symbol from the DLL. You can confirm this by opening your project's property pages and inspecting the C/C++ / Preprocessor / Preprocessor Definitions property: you will find the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSSERVER_EXPORTS&lt;/span&gt; definition there (done for you again by the Project Wizard). &lt;br /&gt;&amp;nbsp; &lt;br /&gt;Now erase everything below these lines and write the following: &lt;br /&gt;&amp;nbsp; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;#include &amp;lt;rapi.h&amp;gt;&lt;/span&gt; &lt;br /&gt;&amp;nbsp; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;extern "C" &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSERVER_API int HTCGSensorStream(DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, IRAPIStream* pStream);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;These lines include the RAPI header file (required for the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;IRAPIStream&lt;/span&gt; declaration) and declare a "C" function named &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorStream&lt;/span&gt;. This is the function that will be called by the RAPI runtime and it cannot be exported with the standard C++ linker names (these are mangled in order to include parameter type information for better run-time type checking). The number and types of the parameters are defined by RAPI for DLL extension functions and these can be of two types: blocking and non-blocking. A blocking extension function works like a regular function call: does its work and returns data back to the caller. A non-blocking function (or streamed call) uses the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;pStream&lt;/span&gt; parameter to keep an open communications channel to the caller on the PC: that's exactly what we'll use. &lt;br /&gt;&amp;nbsp; &lt;br /&gt;Let's create a stub for this function on the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGServer.cpp&lt;/span&gt; file: &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// Starts the HTC G Sensor streaming to the PC via RAPI&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;//&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;int HTCGSensorStream(DWORD cbInput, BYTE* pInput, DWORD* pcbOutput, BYTE** ppOutput, IRAPIStream* pStream)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;*ppOutput = NULL;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;*pcbOutput = 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;LocalFree(pInput);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;pStream-&amp;gt;Release();&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;return 0;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Right now, the function does nothing but return after cleaning up. I'll get back to it after finishing the data server class. Now you can go back to last post's sample code and copy the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor.h&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor.cpp&lt;/span&gt; files to the new poject directory and add them to&amp;nbsp;the project tree. This is all we need to write the final part of the extension DLL: the server class.&lt;br /&gt;&lt;br /&gt;The server class is actually quite simple: it opens the sensor in the constructor, closes it in the destructor and contains a single function (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;Run&lt;/span&gt;) that cntinually reads data from the stream and writes back the sensor data to the listening PC software. This particular implementation uses a polling mechanism that waits for a command from the client and writes sensor data back.&amp;nbsp;It's quite simple to understand how this works, but it's not the best approach performance-wise. From my own experience I have learned that you get the best performance when you put the stream reading and writing in different threads. This allows you to stream data from the server to the client without waiting for a specific command. Performance improves at the cost of complexity.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HRESULT HTCGSensorServer::Run()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; HRESULT hr = S_OK;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; bool bRun = true;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; HTCGSensorData sensorData;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp; while(bRun)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DWORD dwMsg = 0, &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;dwRead, &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;dwWrite;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = m_pStream-&amp;gt;Read(&amp;amp;dwMsg, sizeof(dwMsg), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;dwRead);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(FAILED(hr) || &lt;/span&gt;&lt;span style="font-family: Courier New;"&gt;dwRead != sizeof(dwMsg))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bRun = false;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; switch(dwMsg)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case CMD_QUIT:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bRun = false;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; case CMD_READ:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if(m_sensor.Read(&amp;amp;sensorData))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; hr = m_pStream-&amp;gt;Write(&amp;amp;sensorData, &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sizeof(sensorData), &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;dwWrite);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bRun = false;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; return hr;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;Easy, right? The loop waits for two different commands: one for reading the sensor and the other to stop the loop (thereby exiting the server). Now you just need to call this function from the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorStream&lt;/span&gt; entry point and your server is ready. Add the following lines to the top of the function: &lt;br /&gt;&amp;nbsp; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensorServer server(pStream);&lt;/span&gt; &lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;server.Run();&lt;/span&gt; &lt;br /&gt;&amp;nbsp; &lt;br /&gt;Done. &lt;br /&gt;&amp;nbsp; &lt;br /&gt;On my next post I will implement the PC client DLL. Meanwhile, here's the sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/HTCGServer.zip"&gt;HTCGServer.zip&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-3576110974209860983?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/3576110974209860983/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/htc-g-sensor-rapi-server.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3576110974209860983'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/3576110974209860983'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/05/htc-g-sensor-rapi-server.html' title='The HTC G Sensor RAPI Server'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-7993699317686221282</id><published>2010-04-29T21:09:00.000+01:00</published><updated>2010-04-29T21:09:23.586+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Sensor'/><category scheme='http://www.blogger.com/atom/ns#' term='HTC'/><category scheme='http://www.blogger.com/atom/ns#' term='WTL'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Mobile'/><title type='text'>The HTG G Sensor</title><content type='html'>Here is a very simple application that illustrates how to use the HTC G Sensor. This is included in a number of devices (including my own HTC Touch Pro) and it provides a way to determine the spatial position of the phone by providing "tilt" values for the X, Y and Z coordinate axis.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;/div&gt;Although HTC did not provide a public API for the G Sensor (shame on them for this),&amp;nbsp;&lt;a href="http://scottandmichelle.net/scott/comments.html?entry=784"&gt;Scott Seligman&amp;nbsp;reverse engineered it&lt;/a&gt;&amp;nbsp;which eventually led to a &lt;a href="http://sensorapi.codeplex.com/"&gt;Codeplex project&lt;/a&gt; on this subject. The code you see here was ported from the C# version of the Codeplex project back to C++.&lt;br /&gt;&lt;br /&gt;The application is quite simple: it merely connects to the G Sensor data source, samples it every 200 ms and displays the tilt values on the screen. As usual, I used WTL to write this simple app and its main features are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;HTCGSensor&lt;/span&gt; class that implements an interface to the HTC G Sensor API;&lt;/li&gt;&lt;li&gt;The view window (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CHtcSensorView&lt;/span&gt;) that samples the G Sensor data every 200 milliseconds and displays the tilt values;&lt;/li&gt;&lt;li&gt;The frame window (&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;CHtcSensorFrame&lt;/span&gt;) where the sampling timer is started (see the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;OnCreate&lt;/span&gt; handler)&lt;/li&gt;&lt;/ul&gt;The HTCGSensor class has a few points worth noticing: the sensor DLL is dynamically linked through the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;LoadLibrary&lt;/span&gt; API and the data reading function pointer is cached for better performance. Note that access to the sensor data requires acquiring a handle so, proper finalization is required.&lt;br /&gt;&lt;br /&gt;Sample code: &lt;a href="http://www.primeworks-mobile.com/Downloads/Blog/HtcSensor.zip"&gt;HtcSensor.zip&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The sample application requires an HTC device with a G Sensor like the Diamond. You can use this information in a number of different ways on the device. On a forthcoming post, I will show how you can consume this information on a desktop .NET 3.5 application.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-7993699317686221282?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/7993699317686221282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/04/htg-g-sensor.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7993699317686221282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7993699317686221282'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/04/htg-g-sensor.html' title='The HTG G Sensor'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2423328738091903368.post-7193419497053162772</id><published>2010-04-27T09:31:00.000+01:00</published><updated>2010-04-28T13:56:21.965+01:00</updated><title type='text'>Smiling Smith?</title><content type='html'>Why a new blog? Why this name?&lt;br /&gt;&lt;p&gt;First of all, I want to write about all of my development experiences under one single roof. Until recently I was able to frequently write about native code development on Windows Mobile devices, but due to the recent developments (no native code on WP7), this has become a much harder task. Also, I have recently been working on different technologies (like ASP .NET and XNA) and want to write about them, and the older blogs were too narrow in scope for this.&lt;/p&gt;&lt;p&gt;The blog name is taken from a very old nickname that I never forgot. A few hundred years ago there was a very interesting BBC TV series about an IT consultant named Smith that did a lot of cool stuff. The series was particularly successful on the public television, the only one we had back then. At this time I was working on a very informal team of young developers (remember CP/M?) and there was this older guy who named us all "Smith". Due to my high spirits, I was the smiling one. The Smiling Smith.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2423328738091903368-7193419497053162772?l=smilingsmith.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://smilingsmith.blogspot.com/feeds/7193419497053162772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://smilingsmith.blogspot.com/2010/04/smiling-smith.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7193419497053162772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2423328738091903368/posts/default/7193419497053162772'/><link rel='alternate' type='text/html' href='http://smilingsmith.blogspot.com/2010/04/smiling-smith.html' title='Smiling Smith?'/><author><name>João Paulo Figueira</name><uri>http://www.blogger.com/profile/01808451986712386444</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='25' height='32' src='http://bp0.blogger.com/_AksH5-lumMs/SCQYuaNZMAI/AAAAAAAAAQs/eA23ckrE4Fw/S220/MVP_profile.jpg'/></author><thr:total>4</thr:total></entry></feed>
