Just a quick shout-out to congratulate the latest Silverlight MVPs to the program.  The Microsoft MVP (Most Valuable Professional) program is a recognition program that is in place to recognize and reward those individuals who have been identified by individuals (peers, Microsoft staff, etc.) as experts in their technology field and global contributors to the technology. 

Microsoft MVP logo

As of today (01 OCT 2010) we welcome some new folks to the Silverlight group:

All of these folks are great participants in the Silverlight ecosystem and their local geographies and I congratulate them for their efforts.  Be sure to check out all the Silverlight MVPs and subscribe to their blogs!  Thanks to all of you for helping make a great developer ecosystem!


This work is licensed under a Creative Commons Attribution By license.

October is here…time for an updated Windows 7 Smashing Magazine theme pack!

Alien Invaders calendar

The October themes mostly concentrate on a lot of fall and Halloween themes.  So here is your October 2010 Windows 7 Theme Packs for wallpapers – unfiltered and uncensored – about 45 wallpapers in all.

For details on these and to see past ones, visit the Smashing Magazine Windows 7 Theme information for the specifications I used for the theme pack as well as previous themes.  Want to participate and submit yours?  Join in!


This work is licensed under a Creative Commons Attribution By license.

Recently our team released a service release for Silverlight on 1-Sep-2010.  We affectionately call these “GDR” releases (general distribution release).

NOTE: Other teams have different names for different things.  I’m not sure why Microsoft doesn’t have a standard on these things and it’s funny to hear marketing teams argue the benefit of one name over the other.  For what it is worth, in my eyes, if it isn’t a major milestone release (or at least a ‘dot’ release [4.0->4.1 for example] then it is a service update.  Call it a GDR, Wave X, Service Pack, R2, blah blah.

In the GDR1 release (version 4.0.50826.0) we also released an update to the SDK.  This is where it can start get confusing…allow me to attempt to explain.  GDR1 released:

  • Runtime
  • SDK

On top of that when the release of the Windows Phone Developer Tools released, they shipped the GDR1 bits (and SDK) with them…so while there was no real “tool” update (outside of the required updates for WP7), them shipping the update in the tools effectively put all the new bits on your machine if you installed it.  Most of the time GDR releases are runtime-only releases.  Putting out an SDK release can have some consequences (beneficial if you need the update) as some of you have seen.

The Problem

Here’s what people are seeing…

Hey my users are getting messages to upgrade their Silverlight runtime when my app says minRuntimeVersion=”4.0.50401.0” – what gives?!  I thought this thing was supposed to work!?!?

Every time someone asks me about this, my first question is if they’ve installed the updated SDK.  Almost all the time the answer is yes.  And that is where the issue is (as also they’ve recompiled their app).  Along with the minRuntimeVersion, within the XAP the AppManifest.xml file there is also a RuntimeVersion attribute stamped for the app.  Both of these versions are being set by the version of the SDK.  So when you install a new SDK, that version is the value used here.

NOTE: Your <object> tag minRuntimeVersion isn’t updated on existing projects, but check on a new project and you’ll see it updated there.

So even though you might have specified in the <object> tag minRuntimeVersion for RTW (4.0.50401.0), the fact that the XAP is demanding (via the AppManifest) a later version is what is causing the conflict.

The problem exists when you either want (or have no choice because of auto-updates you subscribe to) the latest Silverlight runtime but as a developer, need to maintain applications and do not want to drive the user to an upgrade to the latest bits.

The Solution

If you find yourself in this situation and don’t want to keep manually changing the AppManifest attribute after each build and re-packaging the XAP, then you can do one thing to keep your environment the way you expect it.

To be clear, what I am outlining here will: enable you to have the latest Silverlight runtime while still building against the RTW of Silverlight 4.

First, you can uninstall Silverlight 4 GDR1 SDK (you can do this via the Add/Remove Control Panel).  Once you’ve done that you can install the Silverlight 4 RTW SDK (4.0.50401.0).

Now you’re done :-).  If you have apps that have been in this problematic state you’ll likely have to do some cleans on your build to ensure that the AppManifest is overridden correctly now.

Future Updates

As I mentioned, generally speaking the GDRs are runtime-only releases.  And actually we issued a second service release in September (GDR2 – 4.0.50917.0). 

NOTE: This GDR2 update has NO OTHER fixes than the issue mentioned in the KB article.  This was fixing a regression that prevented an app from loading/updating.  No other fixes are in this build at this time.

In these cases as a developer all you need to do is ensure you have the latest developer runtime to ensure you can debug, etc.  The Windows developer runtime can be obtained here.

Summary

If you’re in the situation as described above where your users are seeing a prompt that is not expected, you can easily modify your dev environment to prevent this.  The simple summary is:

  • Keep up-to-date on the latest developer runtime
  • Have the RTW SDK installed

The consequences here are if you are doing development with LightSwitch (which requires the updated SDK).

I’m not sure if my rambling here helps, but I tried to just say it how it is.

Hope this helps!


This work is licensed under a Creative Commons Attribution By license.

It looks like the MSDN team has arranged some deep dives into Windows Phone development across the country.  I am sure that for Microsoft developers Windows Phone 7 represents a new opportunity to get out in the marketplace with your XAML skills and get recognized (paid) for your work!  It has been exciting to see a lot of interest from Silverlight developers in Windows Phone 7.

Windows Phone 7

If you are one that hasn’t had the time to soak in the platform or simply haven’t been paying attention, you are in luck.  There are a series of launch events happening across the country, most of which involve a 2-day training (free) for Windows Phone 7.  Here’s what I could gather for the basic agenda for these 2-day workshops:

  • Day 1: Intro, sensors, application lifecycle, tiles, application bar, connecting to services, recording audio, capturing pictures, design guidelines, game development with Silverlight/XNA, etc. – all the fundamentals to get started
  • Day 2: turn your vision into an app, learn about (and submit your app) the Marketplace…or continue learning using a bunch of hands-on labs and the tools to write applications in Silverlight and XNA

It seems like a pretty good deal and you should check them out.  Bringing your own laptop is encouraged and the tools are free!  Check out these opportunities in a city near you – aside form the 2-day events there also looks to be some 1-day sessions as well in some areas.  Check out all the details at http://www.msdnevents.com/wp7 and register for a location near you!

I was spelunking around playing with Silverlight in Windows Phone 7 and specifically the CameraCaptureTask.  The “tasks” are APIs that allow you to interact with phone-specific functionality like the camera, picture picker, phone dialer, etc.  A whole list of the available tasks in the Microsoft.Phone.Tasks namespace can be found in the developer documentation.

I was basically creating a simple application that would allow you to choose (PhotoChooserTask) or take a picture (CameraCaptureTask) and then display the picture (and later post it online or something).  Here was my basic XAML structure:

   1: <Grid x:Name="LayoutRoot" Background="Transparent">
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span>     <span class="kwrd">&lt;</span><span class="html">Grid.RowDefinitions</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>         <span class="kwrd">&lt;</span><span class="html">RowDefinition</span> <span class="attr">Height</span><span class="kwrd">="Auto"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>         <span class="kwrd">&lt;</span><span class="html">RowDefinition</span> <span class="attr">Height</span><span class="kwrd">="*"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     <span class="kwrd">&lt;/</span><span class="html">Grid.RowDefinitions</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>  </pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>     <span class="rem">&lt;!--TitlePanel contains the name of the application and page title--&gt;</span></pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>     <span class="kwrd">&lt;</span><span class="html">StackPanel</span> <span class="attr">x:Name</span><span class="kwrd">="TitlePanel"</span> <span class="attr">Grid</span>.<span class="attr">Row</span><span class="kwrd">="0"</span> <span class="attr">Margin</span><span class="kwrd">="12,17,0,28"</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span>         <span class="kwrd">&lt;</span><span class="html">TextBlock</span> <span class="attr">x:Name</span><span class="kwrd">="ApplicationTitle"</span> <span class="attr">Text</span><span class="kwrd">="PICTURE POSTER"</span> <span class="attr">Style</span><span class="kwrd">="{StaticResource PhoneTextNormalStyle}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum10" class="lnum">  10:</span>         <span class="kwrd">&lt;</span><span class="html">TextBlock</span> <span class="attr">x:Name</span><span class="kwrd">="PageTitle"</span> <span class="attr">Text</span><span class="kwrd">="take and post"</span> <span class="attr">Margin</span><span class="kwrd">="9,-7,0,0"</span> <span class="attr">Style</span><span class="kwrd">="{StaticResource PhoneTextTitle1Style}"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum11" class="lnum">  11:</span>     <span class="kwrd">&lt;/</span><span class="html">StackPanel</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum12" class="lnum">  12:</span>  </pre>
<pre class="alteven"><span id="lnum13" class="lnum">  13:</span>     <span class="rem">&lt;!--ContentPanel - place additional content here--&gt;</span></pre>
<pre class="alteven"><span id="lnum14" class="lnum">  14:</span>     <span class="kwrd">&lt;</span><span class="html">Grid</span> <span class="attr">x:Name</span><span class="kwrd">="ContentPanel"</span> <span class="attr">Grid</span>.<span class="attr">Row</span><span class="kwrd">="1"</span> <span class="attr">Margin</span><span class="kwrd">="12,0,12,0"</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum15" class="lnum">  15:</span>         <span class="kwrd">&lt;</span><span class="html">Image</span> <span class="attr">Margin</span><span class="kwrd">="8,8,8,159"</span> <span class="attr">x:Name</span><span class="kwrd">="ChosenPicture"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum16" class="lnum">  16:</span>         <span class="kwrd">&lt;</span><span class="html">Button</span> <span class="attr">Click</span><span class="kwrd">="OnPostClicked"</span> <span class="attr">x:Name</span><span class="kwrd">="PostPic"</span> <span class="attr">Content</span><span class="kwrd">="POST"</span> <span class="attr">HorizontalAlignment</span><span class="kwrd">="Right"</span> <span class="attr">VerticalAlignment</span><span class="kwrd">="Bottom"</span> <span class="attr">Margin</span><span class="kwrd">="0,0,8,47"</span> <span class="attr">Width</span><span class="kwrd">="199"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum17" class="lnum">  17:</span>         <span class="kwrd">&lt;</span><span class="html">TextBlock</span> <span class="attr">x:Name</span><span class="kwrd">="PostedUri"</span> <span class="attr">TextWrapping</span><span class="kwrd">="Wrap"</span> <span class="attr">VerticalAlignment</span><span class="kwrd">="Bottom"</span> <span class="attr">Margin</span><span class="kwrd">="8,0,8,20"</span><span class="kwrd">/&gt;&lt;/</span><span class="html">Grid</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum18" class="lnum">  18:</span> <span class="kwrd">&lt;/</span><span class="html">Grid</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum19" class="lnum">  19:</span>  </pre>
<pre class="alteven"><span id="lnum20" class="lnum">  20:</span> <span class="rem">&lt;!--Sample code showing usage of ApplicationBar--&gt;</span></pre>
<pre class="alteven"><span id="lnum21" class="lnum">  21:</span> <span class="kwrd">&lt;</span><span class="html">phone:PhoneApplicationPage.ApplicationBar</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum22" class="lnum">  22:</span>     <span class="kwrd">&lt;</span><span class="html">shell:ApplicationBar</span> <span class="attr">IsVisible</span><span class="kwrd">="True"</span> <span class="attr">IsMenuEnabled</span><span class="kwrd">="True"</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum23" class="lnum">  23:</span>         <span class="kwrd">&lt;</span><span class="html">shell:ApplicationBar.MenuItems</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum24" class="lnum">  24:</span>             <span class="kwrd">&lt;</span><span class="html">shell:ApplicationBarMenuItem</span> <span class="attr">Text</span><span class="kwrd">="take picture"</span> <span class="attr">Click</span><span class="kwrd">="OnMenuTakeClicked"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum25" class="lnum">  25:</span>             <span class="kwrd">&lt;</span><span class="html">shell:ApplicationBarMenuItem</span> <span class="attr">Text</span><span class="kwrd">="choose picture"</span> <span class="attr">Click</span><span class="kwrd">="OnMenuChooseClicked"</span><span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum26" class="lnum">  26:</span>             <span class="kwrd">&lt;</span><span class="html">shell:ApplicationBarMenuItem</span> <span class="attr">Text</span><span class="kwrd">="save picture"</span> <span class="attr">Click</span><span class="kwrd">="OnSavePictureClicked"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum27" class="lnum">  27:</span>         <span class="kwrd">&lt;/</span><span class="html">shell:ApplicationBar.MenuItems</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum28" class="lnum">  28:</span>     <span class="kwrd">&lt;/</span><span class="html">shell:ApplicationBar</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum29" class="lnum">  29:</span> <span class="kwrd">&lt;/</span><span class="html">phone:PhoneApplicationPage.ApplicationBar</span><span class="kwrd">&gt;</span></pre>

And the initial code to trigger the task from a MenuItem:

   1: private void OnMenuTakeClicked(object sender, EventArgs e)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     CameraCaptureTask cam = <span class="kwrd">new</span> CameraCaptureTask();</pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>     cam.Completed += <span class="kwrd">new</span> EventHandler&lt;PhotoResult&gt;(OnCameraCaptureCompleted);</pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     cam.Show();</pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span> }</pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>  </pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span> <span class="kwrd">private</span> <span class="kwrd">void</span> OnMenuChooseClicked(<span class="kwrd">object</span> sender, EventArgs e)</pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span> {</pre>
<pre class="alteven"><span id="lnum10" class="lnum">  10:</span>     PhotoChooserTask pix = <span class="kwrd">new</span> PhotoChooserTask();</pre>
<pre class="alteven"><span id="lnum11" class="lnum">  11:</span>     pix.Completed += <span class="kwrd">new</span> EventHandler&lt;PhotoResult&gt;(OnCameraCaptureCompleted);</pre>
<pre class="alteven"><span id="lnum12" class="lnum">  12:</span>     pix.ShowCamera = <span class="kwrd">true</span>;</pre>
<pre class="alteven"><span id="lnum13" class="lnum">  13:</span>     pix.Show();</pre>
<pre class="alteven"><span id="lnum14" class="lnum">  14:</span> }</pre>

As you can see it is pretty simple and brings up the OS-standard camera and/or photo chooser. 

NOTE: if you use the PhotoChooserTask you can also initiate taking a new picture from that task as well.

After the picture is chosen (from a new pic or from a picker) I put the item in the Image control in my XAML:

   1: void OnCameraCaptureCompleted(object sender, PhotoResult e)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     capturedImage = e.ChosenPhoto; <span class="rem">// this is a member variable to store the last chosen pic</span></pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>  </pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     BitmapImage bmp = <span class="kwrd">new</span> BitmapImage();</pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>     bmp.SetSource(e.ChosenPhoto);</pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>  </pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>     ChosenPicture.Source = bmp;</pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span> }</pre>

During this, however, I found that no matter how I held the phone when I took the picture (portrait or landscape), the API always assumed landscape.  I tried looking at some of the device orientation data, but it wasn’t providing the right information at the time I needed it.  It turns out after some internal discussions that others were seeing this as well.  On the device I have (Samsung) the picture snapshot button is in a natural place if you were to hold it landscape.  However, in my current experience with my mobile devices (Android and iPhone) I actually take more pictures in portrait mode.

After some discussion with folks internally, one of our test leads for WP7 reminded everyone that the phone does provide the EXIF information for each picture taken.  One of the attributes of EXIF is orientation (or rotation).  Now all we needed was a method to read the EXIF data in .NET…enter ExifLib.  This is a cool Code Project article and source code download that does a great job providing a simple EXIF reading experience.

The ExifLib as it stood wouldn’t work with the Stream that is provided as a result of the CameraCaptureTask, so a slight modification (or in my case I just created an override) to the function was needed for the library.  Here’s the additional override I added:

   1: public static JpegInfo ReadJpeg(Stream FileStream, string FileName)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     DateTime now = DateTime.Now;</pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>     ExifReader reader = <span class="kwrd">new</span> ExifReader(FileStream);</pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     reader.info.FileSize = (<span class="kwrd">int</span>)FileStream.Length;</pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>     reader.info.FileName = <span class="kwrd">string</span>.Format(<span class="str">"{0}.jpg"</span>, FileName);</pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>     reader.info.LoadTime = (TimeSpan)(DateTime.Now - now);</pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>     <span class="kwrd">return</span> reader.info;</pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span> }</pre>

Now with that in place, I could accomplish taking my picture and read the EXIF data and apply the appropriate transform based on the orientation data.  The first thing I had to do was to create a RotateTransform on my Image element as well as set the RenderTransformOrigin on the Image element:

   1: <Image Margin="8,8,8,159" x:Name="ChosenPicture" RenderTransformOrigin="0.5,0.5">
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span>     <span class="kwrd">&lt;</span><span class="html">Image.RenderTransform</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>         <span class="kwrd">&lt;</span><span class="html">RotateTransform</span> <span class="attr">x:Name</span><span class="kwrd">="ImageRotate"</span> <span class="kwrd">/&gt;</span></pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>     <span class="kwrd">&lt;/</span><span class="html">Image.RenderTransform</span><span class="kwrd">&gt;</span></pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span> <span class="kwrd">&lt;/</span><span class="html">Image</span><span class="kwrd">&gt;</span></pre>

Now in code in my completed handler for the task I modified it to look at the EXIF orientation data and apply the correct rotation to show the image:

   1: void OnCameraCaptureCompleted(object sender, PhotoResult e)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     capturedImage = e.ChosenPhoto;</pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>  </pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     BitmapImage bmp = <span class="kwrd">new</span> BitmapImage();</pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>     bmp.SetSource(e.ChosenPhoto);</pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>  </pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>     ChosenPicture.Source = bmp;</pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span>  </pre>
<pre class="alteven"><span id="lnum10" class="lnum">  10:</span>     <span class="rem">// figure out the orientation from EXIF data</span></pre>
<pre class="alteven"><span id="lnum11" class="lnum">  11:</span>     e.ChosenPhoto.Position = 0;</pre>
<pre class="alteven"><span id="lnum12" class="lnum">  12:</span>     JpegInfo info = ExifReader.ReadJpeg(e.ChosenPhoto, e.OriginalFileName);</pre>
<pre class="alteven"><span id="lnum13" class="lnum">  13:</span>     PostedUri.Text = info.Orientation.ToString();</pre>
<pre class="alteven"><span id="lnum14" class="lnum">  14:</span>  </pre>
<pre class="alteven"><span id="lnum15" class="lnum">  15:</span>     <span class="kwrd">switch</span> (info.Orientation)</pre>
<pre class="alteven"><span id="lnum16" class="lnum">  16:</span>     {</pre>
<pre class="alteven"><span id="lnum17" class="lnum">  17:</span>         <span class="kwrd">case</span> ExifOrientation.TopLeft:</pre>
<pre class="alteven"><span id="lnum18" class="lnum">  18:</span>         <span class="kwrd">case</span> ExifOrientation.Undefined:</pre>
<pre class="alteven"><span id="lnum19" class="lnum">  19:</span>             ImageRotate.Angle = 0d;</pre>
<pre class="alteven"><span id="lnum20" class="lnum">  20:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum21" class="lnum">  21:</span>         <span class="kwrd">case</span> ExifOrientation.TopRight:</pre>
<pre class="alteven"><span id="lnum22" class="lnum">  22:</span>             ImageRotate.Angle = 90d;</pre>
<pre class="alteven"><span id="lnum23" class="lnum">  23:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum24" class="lnum">  24:</span>         <span class="kwrd">case</span> ExifOrientation.BottomRight:</pre>
<pre class="alteven"><span id="lnum25" class="lnum">  25:</span>             ImageRotate.Angle = 180d;</pre>
<pre class="alteven"><span id="lnum26" class="lnum">  26:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum27" class="lnum">  27:</span>         <span class="kwrd">case</span> ExifOrientation.BottomLeft:</pre>
<pre class="alteven"><span id="lnum28" class="lnum">  28:</span>             ImageRotate.Angle = 270d;</pre>
<pre class="alteven"><span id="lnum29" class="lnum">  29:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum30" class="lnum">  30:</span>     }</pre>
<pre class="alteven"><span id="lnum31" class="lnum">  31:</span> }</pre>

Now I’ve got my flexibility in my application and don’t have to worry about the orientation. 

Now of course this only helps for the display of the information.  If you were to use the libraries to save the image you’d still have the issue of an incorrect orientation on the picture.  Again, iterating with our test team internally (thanks Stefan!!!) here’s a modified view of the world.

First, instead of rotating the Image element, let’s just rotate the actual Pixels themselves:

   1: void OnCameraCaptureCompleted(object sender, PhotoResult e)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     <span class="rem">// figure out the orientation from EXIF data</span></pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>     e.ChosenPhoto.Position = 0;</pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>     JpegInfo info = ExifReader.ReadJpeg(e.ChosenPhoto, e.OriginalFileName);</pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>  </pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>     _width = info.Width;</pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>     _height = info.Height;</pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span>     _orientation = info.Orientation;</pre>
<pre class="alteven"><span id="lnum10" class="lnum">  10:</span>  </pre>
<pre class="alteven"><span id="lnum11" class="lnum">  11:</span>     PostedUri.Text = info.Orientation.ToString();</pre>
<pre class="alteven"><span id="lnum12" class="lnum">  12:</span>  </pre>
<pre class="alteven"><span id="lnum13" class="lnum">  13:</span>     <span class="kwrd">switch</span> (info.Orientation)</pre>
<pre class="alteven"><span id="lnum14" class="lnum">  14:</span>     {</pre>
<pre class="alteven"><span id="lnum15" class="lnum">  15:</span>         <span class="kwrd">case</span> ExifOrientation.TopLeft:</pre>
<pre class="alteven"><span id="lnum16" class="lnum">  16:</span>         <span class="kwrd">case</span> ExifOrientation.Undefined:</pre>
<pre class="alteven"><span id="lnum17" class="lnum">  17:</span>             _angle = 0;</pre>
<pre class="alteven"><span id="lnum18" class="lnum">  18:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum19" class="lnum">  19:</span>         <span class="kwrd">case</span> ExifOrientation.TopRight:</pre>
<pre class="alteven"><span id="lnum20" class="lnum">  20:</span>             _angle = 90;</pre>
<pre class="alteven"><span id="lnum21" class="lnum">  21:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum22" class="lnum">  22:</span>         <span class="kwrd">case</span> ExifOrientation.BottomRight:</pre>
<pre class="alteven"><span id="lnum23" class="lnum">  23:</span>             _angle = 180;</pre>
<pre class="alteven"><span id="lnum24" class="lnum">  24:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum25" class="lnum">  25:</span>         <span class="kwrd">case</span> ExifOrientation.BottomLeft:</pre>
<pre class="alteven"><span id="lnum26" class="lnum">  26:</span>             _angle = 270;</pre>
<pre class="alteven"><span id="lnum27" class="lnum">  27:</span>             <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum28" class="lnum">  28:</span>     }</pre>
<pre class="alteven"><span id="lnum29" class="lnum">  29:</span>  </pre>
<pre class="alteven"><span id="lnum30" class="lnum">  30:</span>     <span class="kwrd">if</span> (_angle &gt; 0d)</pre>
<pre class="alteven"><span id="lnum31" class="lnum">  31:</span>     {</pre>
<pre class="alteven"><span id="lnum32" class="lnum">  32:</span>         capturedImage = RotateStream(e.ChosenPhoto, _angle);</pre>
<pre class="alteven"><span id="lnum33" class="lnum">  33:</span>     }</pre>
<pre class="alteven"><span id="lnum34" class="lnum">  34:</span>     <span class="kwrd">else</span></pre>
<pre class="alteven"><span id="lnum35" class="lnum">  35:</span>     {</pre>
<pre class="alteven"><span id="lnum36" class="lnum">  36:</span>         capturedImage = e.ChosenPhoto;</pre>
<pre class="alteven"><span id="lnum37" class="lnum">  37:</span>     }</pre>
<pre class="alteven"><span id="lnum38" class="lnum">  38:</span>  </pre>
<pre class="alteven"><span id="lnum39" class="lnum">  39:</span>     BitmapImage bmp = <span class="kwrd">new</span> BitmapImage();</pre>
<pre class="alteven"><span id="lnum40" class="lnum">  40:</span>     bmp.SetSource(capturedImage);</pre>
<pre class="alteven"><span id="lnum41" class="lnum">  41:</span>  </pre>
<pre class="alteven"><span id="lnum42" class="lnum">  42:</span>     ChosenPicture.Source = bmp;           </pre>
<pre class="alteven"><span id="lnum43" class="lnum">  43:</span> }</pre>
<pre class="alteven"><span id="lnum44" class="lnum">  44:</span>  </pre>
<pre class="alteven"><span id="lnum45" class="lnum">  45:</span> <span class="kwrd">private</span> Stream RotateStream(Stream stream, <span class="kwrd">int</span> angle)</pre>
<pre class="alteven"><span id="lnum46" class="lnum">  46:</span> {</pre>
<pre class="alteven"><span id="lnum47" class="lnum">  47:</span>     stream.Position = 0;</pre>
<pre class="alteven"><span id="lnum48" class="lnum">  48:</span>     <span class="kwrd">if</span> (angle % 90 != 0 || angle &lt; 0) <span class="kwrd">throw</span> <span class="kwrd">new</span> ArgumentException();</pre>
<pre class="alteven"><span id="lnum49" class="lnum">  49:</span>     <span class="kwrd">if</span> (angle % 360 == 0) <span class="kwrd">return</span> stream;</pre>
<pre class="alteven"><span id="lnum50" class="lnum">  50:</span>  </pre>
<pre class="alteven"><span id="lnum51" class="lnum">  51:</span>     BitmapImage bitmap = <span class="kwrd">new</span> BitmapImage();</pre>
<pre class="alteven"><span id="lnum52" class="lnum">  52:</span>     bitmap.SetSource(stream);</pre>
<pre class="alteven"><span id="lnum53" class="lnum">  53:</span>     WriteableBitmap wbSource = <span class="kwrd">new</span> WriteableBitmap(bitmap);</pre>
<pre class="alteven"><span id="lnum54" class="lnum">  54:</span>  </pre>
<pre class="alteven"><span id="lnum55" class="lnum">  55:</span>     WriteableBitmap wbTarget = <span class="kwrd">null</span>;</pre>
<pre class="alteven"><span id="lnum56" class="lnum">  56:</span>     <span class="kwrd">if</span> (angle % 180 == 0)</pre>
<pre class="alteven"><span id="lnum57" class="lnum">  57:</span>     {</pre>
<pre class="alteven"><span id="lnum58" class="lnum">  58:</span>         wbTarget = <span class="kwrd">new</span> WriteableBitmap(wbSource.PixelWidth, wbSource.PixelHeight);</pre>
<pre class="alteven"><span id="lnum59" class="lnum">  59:</span>     }</pre>
<pre class="alteven"><span id="lnum60" class="lnum">  60:</span>     <span class="kwrd">else</span></pre>
<pre class="alteven"><span id="lnum61" class="lnum">  61:</span>     {</pre>
<pre class="alteven"><span id="lnum62" class="lnum">  62:</span>         wbTarget = <span class="kwrd">new</span> WriteableBitmap(wbSource.PixelHeight, wbSource.PixelWidth);</pre>
<pre class="alteven"><span id="lnum63" class="lnum">  63:</span>     }</pre>
<pre class="alteven"><span id="lnum64" class="lnum">  64:</span>  </pre>
<pre class="alteven"><span id="lnum65" class="lnum">  65:</span>     <span class="kwrd">for</span> (<span class="kwrd">int</span> x = 0; x &lt; wbSource.PixelWidth; x++)</pre>
<pre class="alteven"><span id="lnum66" class="lnum">  66:</span>     {</pre>
<pre class="alteven"><span id="lnum67" class="lnum">  67:</span>         <span class="kwrd">for</span> (<span class="kwrd">int</span> y = 0; y &lt; wbSource.PixelHeight; y++)</pre>
<pre class="alteven"><span id="lnum68" class="lnum">  68:</span>         {</pre>
<pre class="alteven"><span id="lnum69" class="lnum">  69:</span>             <span class="kwrd">switch</span> (angle % 360)</pre>
<pre class="alteven"><span id="lnum70" class="lnum">  70:</span>             {</pre>
<pre class="alteven"><span id="lnum71" class="lnum">  71:</span>                 <span class="kwrd">case</span> 90:</pre>
<pre class="alteven"><span id="lnum72" class="lnum">  72:</span>                     wbTarget.Pixels[(wbSource.PixelHeight - y - 1) + x * wbTarget.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];</pre>
<pre class="alteven"><span id="lnum73" class="lnum">  73:</span>                     <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum74" class="lnum">  74:</span>                 <span class="kwrd">case</span> 180:</pre>
<pre class="alteven"><span id="lnum75" class="lnum">  75:</span>                     wbTarget.Pixels[(wbSource.PixelWidth - x - 1) + (wbSource.PixelHeight - y - 1) * wbSource.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];</pre>
<pre class="alteven"><span id="lnum76" class="lnum">  76:</span>                     <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum77" class="lnum">  77:</span>                 <span class="kwrd">case</span> 270:</pre>
<pre class="alteven"><span id="lnum78" class="lnum">  78:</span>                     wbTarget.Pixels[y + (wbSource.PixelWidth - x - 1) * wbTarget.PixelWidth] = wbSource.Pixels[x + y * wbSource.PixelWidth];</pre>
<pre class="alteven"><span id="lnum79" class="lnum">  79:</span>                     <span class="kwrd">break</span>;</pre>
<pre class="alteven"><span id="lnum80" class="lnum">  80:</span>             }</pre>
<pre class="alteven"><span id="lnum81" class="lnum">  81:</span>         }</pre>
<pre class="alteven"><span id="lnum82" class="lnum">  82:</span>     }</pre>
<pre class="alteven"><span id="lnum83" class="lnum">  83:</span>     MemoryStream targetStream = <span class="kwrd">new</span> MemoryStream();</pre>
<pre class="alteven"><span id="lnum84" class="lnum">  84:</span>     wbTarget.SaveJpeg(targetStream, wbTarget.PixelWidth, wbTarget.PixelHeight, 0, 100);</pre>
<pre class="alteven"><span id="lnum85" class="lnum">  85:</span>     <span class="kwrd">return</span> targetStream;</pre>
<pre class="alteven"><span id="lnum86" class="lnum">  86:</span> }</pre>

Notice here that OnCameraCaptureCompleted is different in that we first check the orientation and if needed rotate the pixels using the newly introduced RotateStream method.  The resulting stream is what we actually set on our Image element and no need for RotateTransform at this point.  I can then even have a menu item save the picture to the media library on the device:

   1: private void OnSavePictureClicked(object sender, EventArgs e)
<pre class="alteven"><span id="lnum2" class="lnum">   2:</span> {</pre>
<pre class="alteven"><span id="lnum3" class="lnum">   3:</span>     <span class="kwrd">if</span> (capturedImage != <span class="kwrd">null</span>)</pre>
<pre class="alteven"><span id="lnum4" class="lnum">   4:</span>     {</pre>
<pre class="alteven"><span id="lnum5" class="lnum">   5:</span>         capturedImage.Seek(0, 0); <span class="rem">// necessary to initiate the stream correctly before save</span></pre>
<pre class="alteven"><span id="lnum6" class="lnum">   6:</span>  </pre>
<pre class="alteven"><span id="lnum7" class="lnum">   7:</span>         MediaLibrary ml = <span class="kwrd">new</span> MediaLibrary();</pre>
<pre class="alteven"><span id="lnum8" class="lnum">   8:</span>         <span class="kwrd">try</span></pre>
<pre class="alteven"><span id="lnum9" class="lnum">   9:</span>         {</pre>
<pre class="alteven"><span id="lnum10" class="lnum">  10:</span>             Picture p = ml.SavePicture(Guid.NewGuid().ToString(), capturedImage);</pre>
<pre class="alteven"><span id="lnum11" class="lnum">  11:</span>             PostedUri.Text += <span class="str">":"</span> + p.Name;</pre>
<pre class="alteven"><span id="lnum12" class="lnum">  12:</span>         }</pre>
<pre class="alteven"><span id="lnum13" class="lnum">  13:</span>         <span class="kwrd">catch</span> (Exception ex)</pre>
<pre class="alteven"><span id="lnum14" class="lnum">  14:</span>         {</pre>
<pre class="alteven"><span id="lnum15" class="lnum">  15:</span>             PostedUri.Text = ex.Message;</pre>
<pre class="alteven"><span id="lnum16" class="lnum">  16:</span>         }</pre>
<pre class="alteven"><span id="lnum17" class="lnum">  17:</span>     }</pre>
<pre class="alteven"><span id="lnum18" class="lnum">  18:</span> }</pre>

The MediaLibrary is a part of Microsoft.Xna.Framework.Media and provides the easy functionality of saving to the device.  And upon sync (or sharing) my image is what I expected when I took the picture using the CameraCaptureTask.

Here is my final project sample (lots of debug code in there, but you should get the point): WindowsPhoneApplication63.zip (requires the Windows Phone Developer Tools)

Hope this helps!