Pretty empty so far, if we load a digital comic (only .cbz format supported in this demo) and select the Devices charm we get this.
That’s right! that’s Captain America himself, including Bucky. And oh yeah, the xbox shows up in the Devices charm as well. After selecting the xbox from the list of devices we get this.
And here it is playing on my TV (yes that’s a Sony, because Microsoft doesn’t build televisions yet )
Pretty cool eh? Let’s check under the hood.
First, a digital comic mostly exists in either .cbz or .cbr format. They’re actually nothing more then a zip or a rar file (Comic Book Zip and Comic Book Rar). Since WinRT has the ZipArchive class we can support .cbz out of the box, for cbr format we would need to find a library that supports rar files but that’s outside the scope of this post.
First the XAML, the main control here is a FlipView, that allows for touch and mouse support out of the box. The FlipView is bound to a collection of bitmap images that get loaded from the digital comic. Next to the FlipView there’s also an appbar containing the load file button and a textblock that shows the connection to other devices.
The FlipView template is just a simple Image control, nothing special in the XAML, the magic is in the code behind.
First some fields that we’ll need later on
We’re going to take a look at how to load the cbz file first, I’ll go over this quickly as the main focus of this post is the PlayTo contract.
All we do in the button’s eventhandler is initializing the field that will hold all the pages, call the function that will load the file and if it contains any items it will set the FlipView’s itemssource to that list. Next up: the function to load the comic.
We start by initializing the FileOpenPicker, allowing our user to select the comic he/she wants to read. We add a suggested location where the FileOpenPicker should start and add the filetypes it should look for. The PickFileAsync method shows the actual filepicker to the user, the user selects the cbz file he wants and it gets loaded into the storageFile variable. The file gets read in as an IRandomAccessStream. We need that stream to create a ZipArchive instance. Once we have that we can loop through all files in that zip archive. Each .jpg file in that zip archive gets read into a byte array that we then convert into a bitmap by using RandomStream, an implementation of IRandomAccessStream (if you want to see the implementation, the project is attached to this post at the bottom). The bitmap image then gets added to the list. When they’re all done the list gets returned to the caller.
That’s it for loading the comic, let’s take a look at the sharing to other devices in your network.
We need to initialize the PlayTo contract, I’ll be doing this from the constructor
PlayToManager is the class that we need, we get this for free from the WinRT framework. The GetForCurrentView() method returns an instance of the PlayToManager class bound to this page. Once we have the instance we attach an eventhandler to the SourceRequested and the SourceSelected events. The SourceRequested event will fire as soon as the user hits the Devices charm, this is where we’ll prepare the first media element for streaming. The SourceSelected event fires when the user selects a source, obviously.
The OnSourceRequested eventhandler needs to be marked as async. First we get the deferral, then we need to run some async code, Dispatcher.RunAsync is the same as calling an async method with await on this line. The PlayTo contract works with certain XAML controls. In our case we need the Image control, that’s why we’ve set the itemtemplate of the FlipView to be an Image. We’ll take a look at the GetChildren() method in a minute, for now just know that it returns a list of all Image controls inside the FlipView. We take the first element in the returned list and that’s the element that we’ll stream to the device. The arguments have a property of type PlayToSourceRequest, that one has a SetSource function that takes in a PlayToSource object and that’s a property of the Image control. We set the current image to the _current field and mark the deferral as complete.
Phew that was quite some work. Don’t worry, the hard part is over (yes this was really the hard part). Now a quick look at that GetChildren() function.
The function takes in a DependencyObject and starts walking through its visual tree. We try to cast each item as an Image, if that cast fails the variable will contain null, a quick check there and if it isn’t null we add it to the list which we then return.
The OnSourceSelected is only used to set the name of the selected source to the textblock
And that’s enough to stream the first image, when you run this code and select the Devices charm the first page of the comic should show up on your device. All there’s left now is to go back and forward in the comic. In the app itself this already works, the FlipView takes care of navigating between the pages. Before we start developing this we need to make a small halt and take a look at how the FlipView actually works. First thought in my head was “okay this is easy, I just get all the image controls in the FlipView and I’m golden”. That was a big nono. The itemspanel of a FlipView is actually a VirtualizingStackPanel, meaning that at any given time there are maximum three Image controls inside the FlipView, usually previous-current-next. As soon as we navigate to another page the FlipView automatically loads in the next item in line. This can easily be seen by using a handy tool called XamlSpy. XamlSpy allows us to view the entire visual tree of any XAML based application. When we view the default visual tree of a FlipView after loading a comic we get this.
As you can see, we only have three FlipViewItems here. When we change the FlipView’s paneltemplate to this
and we load the same comic in XamlSpy we get this result
Quite the difference I would say. The VirtualizingStackPanel is lighter on memory usage, since some comics can be quite large we’ll stick to the default template.
Now that we have that cleared out, let’s take a look at what happens when we browse to the next page of the comic.
First, this code does not need to be executed when we’re not connected to any device, if we are we need to run the next block of code asynchronously. First the code fetches all the available Image controls inside the FlipView, we save a reference to the middle one because that one is the one currently shown in the FlipView. The field _current contains the image currently shown on the external device, we need to set that field’s PlayToSource.Next property. That property always needs to be set on the current image before the PlayNext() method is called. Once that’s set we call the aforementioned PlayNext() method. That method will sent the control that is set to the PlayToSource.Next property to the connected device. To end we set the image control that was just send to the device to the _current field so that it can be called upon on the next run.
In this post I have shown how you can share media content from your Windows Store application to an external device like the Xbox 360. The project used in this post can be downloaded from my SkyDrive
This is an imported post. It was imported from my old blog using an automated tool and may contain formatting errors and/or broken images.