-
New SDK update for Windows Phone 8
Microsoft, last Friday, has released a new update for the Windows Phone 8 SDK, that works both with Visual Studio 2012 (it’s required, at least, the Update 2 installed) and Visual Studio 2013 Preview. The update doesn’t include any new API, but it just add 4 new emulator images, aligned with the GDR2 update of the operating system. This way, you can test your apps against the latest Windows Phone release (even you shouldn’t expect to find compatibility issues), that, other than adding new consumer features, it fixed a couple of bugs in the API (the most noticeable one is about the HttpWebRequest, that now is able to work properly with cookies).
You can download the new update from here: the file size is about 1 GB.
in
-
Some clarifications about Windows Phone, Windows 8.1 and Visual Studio 2013
Yesterday Microsoft has released the much anticipated Windows 8.1 Preview, together with the first Preview of Visual Studio 2013. The Windows team worked really hard in the latest month and I think that the results are really good: Windows 8.1 is a big step forward from Windows 8, both for tablet users and desktop users. Tablet users can now enjoy many more nice features, like the new live tiles, the new snapped mode, the new control panel (that now can be used to customize almost every option without having to use the old desktop control panel). Desktop users, instead, should now find a more familiar environment, thanks to the return of the start menu, the option to boot the pc directly on the desktop and a new Apps screen, that lists all the apps installed on your computer and that replaces the old Start menu approach.
Windows 8.1 is interesting also for developers: with something like 5000 new APIs, I think that we’ll have much fun in the next months Actually, the best way to be updated on what’s going at BUILD is to pay a visit to the Channel 9 website, that will make available all the recordings of the sessions that will cover all the new Windows 8.1 features for developers. I think that, in the near future, you’ll see also some stuff covered in this blog
With this post, I just would like to highlight some things that can be interesting if you want to start to play with the new stuff and, at the same, keep working on Windows Phone development (as expected, nothing has been announced about the next Windows Phone version, the main focus of the conference is Windows).
Here we go!
- The commercial Visual Studio 2013 Preview versions have built-in Windows Phone development support, but just for Windows Phone 8. If you want to keep developing for Windows Phone 7, you’ll need Visual Studio 2012. It’s not a big deal since, fortunately, it works side by side with Visual Studio 2013 without problems.
- The same if you use the Express version of Visual Studio 2013, that doesn’t support Windows Phone projects: you still need the 2012 Express release that comes with the SDK.
- If you want to try and install Windows 8.1 Preview on your machine, Visual Studio 2012 and Windows Phone SDK work just fine. You’ll just have to install the Visual Studio 2012 Update 3 (released yesterday), that will fix some compatibility issues with the emulator. Cliff Simpkins just pointed the fix on his blog.
Here are the links for the download:
- Windows 8.1 Preview: http://windows.microsoft.com/en-us/windows-8/download-preview
- Visual Studio 2013 Preview: http://www.microsoft.com/visualstudio/eng/2013-downloads
Just keep in mind that the upgrade process from the Preview release to the RTM (once it will be released) won’t be as smooth as if you update it from a “clean” Windows 8 installation: you’ll be able to keep your data, but you’ll have to reinstall all the apps (both Windows Store and desktop apps).
But there’s more! With the beginning of the BUILD conference, Microsoft has launched a very cool initiative for Windows Phone developers: the entry price to purchase a new Windows Phone developer account has been cut from 99$ to 19$ until the end of the August. The promotion is valid just for new accounts: it doesn’t apply for renewals. To get it, you’ll simply have to start the registration process in the standard way on the Dev Center.
in
-
How to apply a background to a Panorama using binding
In the next few days I’m going to publish a new application called Movies Tracker, which can be used to keep track of the movies you’ve already seen or that you would like to see. The application is totally built with the MVVM pattern, using Caliburn Micro as framework. The application makes great use of the Panorama control: in the main page, I use it to display different movies categories; in the movie detail, I use it to display different information about the movie (the poster, the cast, the story, etc.). To give to the application a better look and feel, I’ve decided to use as a background of every Panorama an image taken from the movie, kindly provided by The Movie Database. And here comes the problem: since I’m using MVVM, the path of the image I want to display as background is available in the ViewModel, so I need to assign it as Panorama’s background using binding, like in the following sample:
<phone:Panorama> <phone:Panorama.Background> <ImageBrush ImageSource="{Binding Path=BackgroundImage}" /> </phone:Panorama.Background> <phone:PanoramaItem Header="item 1" /> <phone:PanoramaItem Header="item 1" /> </phone:Panorama>
Nothing strange right? So, which is the problem? That the above code simply doesn’t work: when you assign, in your ViewModel, an image path to the BackgroundImage property **nothing happens. Unfortunately, the Panorama controls has a bug, so binding an image path to its Background property simply doesn’t work.
And here comes attached properties to the rescue! Attached properties is a powerful way to extend an existing control, provided by the XAML infrastructure: basically, you can add your custom property to an already existing control and you can decide the logic to apply when that property is set with a value. The workaround to this bug is to create an attached property, where we’re going to set the path of the image. When this value is set, we’re going to manually set the Background property of the control with the image from code: this way, everything will work fine, because the bug happens only when you use binding.
But we’re going to do more and overcome, at the same time, a limitation of the ImageBrush control: the ImageSource property, which contains the image path, supports only remote paths or local paths inside the Visual Studio project, so it’s ok to do something like in the following samples:
<phone:Panorama> <phone:Panorama.Background> <ImageBrush ImageSource="http://www.mywebsite.com/background.png" /> </phone:Panorama.Background> <phone:PanoramaItem Header="item 1" /> <phone:PanoramaItem Header="item 1" /> </phone:Panorama> <phone:Panorama> <phone:Panorama.Background> <ImageBrush ImageSource="/Assets/Images/Background.png" /> </phone:Panorama.Background> <phone:PanoramaItem Header="item 1" /> <phone:PanoramaItem Header="item 1" /> </phone:Panorama>
What if the image is stored in the Isolated Storage? You can’t assign it using binding, but you’ll have to manually load in the code using a BitmapImage, like in the following sample:
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream stream = store.OpenFile("Background.png", FileMode.Open)) { BitmapImage image = new BitmapImage(); image.SetSource(stream); ImageBrush brush = new ImageBrush { Opacity = 0.3, Stretch = Stretch.UniformToFill, ImageSource = image, }; panorama.Background = brush; } }
The problem of this approach is that it works only in code behind, because you’ll need a reference (using the x:Name property) to the Panorama control: you can’t do that in a ViewModel. We’re going to support also this scenario in our attached property: if the image path is prefixed with the isostore:/ protocol, we’re going to load it from the isolated storage.
Let’s see the code of the attached property first:
public class BackgroundImageDownloader { public static readonly DependencyProperty SourceProperty = DependencyProperty.RegisterAttached("Source", typeof(string), typeof(BitmapImage), new PropertyMetadata(null, callback)); public static void SetSource(DependencyObject element, string value) { element.SetValue(SourceProperty, value); } public static string GetSource(DependencyObject element) { return (string)element.GetValue(SourceProperty); } private static async void callback(DependencyObject d, DependencyPropertyChangedEventArgs e) { Panorama panorama = d as Panorama; if (panorama != null) { var path = e.NewValue as string; { if (!string.IsNullOrEmpty(path)) { if (path.StartsWith("isostore:/")) { string localPath = path.Substring(10); using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) { using (IsolatedStorageFileStream stream = store.OpenFile(localPath, FileMode.Open)) { BitmapImage image = new BitmapImage(); image.SetSource(stream); ImageBrush brush = new ImageBrush { Opacity = 0.3, Stretch = Stretch.UniformToFill, ImageSource = image, }; panorama.Background = brush; } } } else { BitmapImage image = new BitmapImage(new Uri(path, UriKind.Absolute)); ImageBrush brush = new ImageBrush { Opacity = 0.3, Stretch = Stretch.UniformToFill, ImageSource = image, }; panorama.Background = brush; } } } } } }
We’ve defined a new property called Source, which can be used with a Panorama control: when a value is assigned to the property, the method called callback is executed and it contains two important parameters; the first one, d, which type is DependencyObject, is the control which the property has been attached to (in our case, it will always be a Panorama control); the second one, which type is DependencyPropertyChangedEventArgs, contains the value assigned to the property.
With these information we’ll be able to get a reference to the Panorama control which we want to apply the background to and the path of the image to load. We retrieve the path using the NewValue property of the DependencyPropertyChangedEventArgs object and we check if it starts with isostore:/ or not. If that’s the case, we load the image from the Isolated Storage using the Storage APIs: once we get the image’s stream, we can create a new BitmapImage object and assign to it using the SetSource property. In the end, we create a new ImageBrush object and we assign the image as ImageSource: this way, we have a proper ImageBrush that we can assign to the Background property of the Panorama.
In case the image doesn’t come from the isolated storage, we simply create a new BitmapImage passing the Url, then we repeat the same operation as before: we create a new ImageBrush object, we assign the image as ImageSource and we set it as value of the Background property of the Panorama control.
How to use this attached property? First, we need to define in the XAML the namespace that contains our property (in the sample, I’ve called it panoramaBinding), than we can simply use the following code:
<phone:Panorama panoramaBinding:BackgroundImageDownloader.Source="{Binding BackgroundPath}"> <phone:PanoramaItem Header="item 1" /> <phone:PanoramaItem Header="item 2" /> </phone:Panorama>
Thanks to our attached property, BackgroundPath can be either a remote url or a local url: we just need to remember to add the isostore:/ prefix in the second case.
Here is a sample ViewModel where the BackgroundPath is set as a remote url:
public class MainViewModel : ViewModelBase { private string backgroundPath; public string BackgroundPath { get { return backgroundPath; } set { backgroundPath = value; RaisePropertyChanged(() => BackgroundPath); } } public MainViewModel() { BackgroundPath = "http://4.bp.blogspot.com/-m0CqTN988_U/USd9rxvPikI/AAAAAAAADDY/4JKRsm3cD8c/s1600/free-wallpaper-downloads.jpg"; } }
And here’s another sample where I’ve defined a command, that is triggered when the user presses a button in the page: using the new Windows Phone 8 APIs I copy some pictures in the isolated storage and then I set the BackgroundPath property using a local path:
public class MainViewModel : ViewModelBase { private string backgroundPath; public string BackgroundPath { get { return backgroundPath; } set { backgroundPath = value; RaisePropertyChanged(() => BackgroundPath); } } public RelayCommand LoadImages { get { return new RelayCommand(async () => { StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync("Assets\\Images\\"); IReadOnlyList<StorageFile> files = await folder.GetFilesAsync(); foreach (StorageFile file in files) { await file.CopyAsync(ApplicationData.Current.LocalFolder, file.Name, NameCollisionOption.ReplaceExisting); } BackgroundPath = "isostore://Balls.jpg"; }); } } }
In both cases the result will be what you expect: the image will be displayed as background of the Panorama control. However, be aware that loading too big images can lead to many performance issues, since they can consume a lot of memory. But we’ll talk about this in another post
In the meantime, you can play with the sample project!
in
subscribe via RSS