Sergiy Baydachnyy

Blog about technologies

Archive for the ‘Windows 10’ Category

Win2D: How to use graphics without knowledge in DirectX

with one comment

Direct2D is a very good technology but using of it requires some knowledge in DirectX. Yes, DirectX is cool but lots of developers who build business applications have never used DirectX in their entire life. That’s why many of them ask about Direct2D features like about a separate Windows Runtime API, which is ready for non-game developers. Win2D is such an API.

Win2D is a Windows Runtime API which is available for C++ and C# developers and brings GPU optimized 2D graphic to Windows 8.x/Windows 10 XAML applications.

The best way to start working with Win2D is to visit Win2D Team Blog where you can find links to the documentation, sample code, source code (Win2D is an open source project) etc. But if you want to understand the full power of Win2D it is better to start develop something using this API. So, let’s look at some useful classes there and learn how to start developing with Win2D.

Since Win2D is an open source project and is not a part of Universal Windows Platform by default, you need to use NuGet package manager to add the latest version of Win2D libraries (use Win2D.uwp).


NuGet will add a reference to Microsoft.Graphics.Canvas assembly what contains all Win2D classes. So, it’s easy to open this assembly and find all namespaces and classes at the same place.


Just open Microsoft.Graphics.Canvas.UI.Xaml namespace and find all XAML controls there. You can see that there are two classes based on UserControl: CanvasAnimatedControl and CanvasControl. Additionally, there is CanvasSwapChainPanel class which is derived from Grid class. Let’s see these classes in more details.

First of all you need to add Microsoft.Graphics.Canvas.UI.Xaml namespace to your XAML file:


Right after that you can use the controls there and we will start with the simplest one, CanvasControl.

<canvas:CanvasControl Draw="CanvasControl_Draw"></canvas:CanvasControl>

CanvasControl is a place for drawing but we need some places to implement drawing algorithms. That’s why CanvasControl has two important events: Draw and CreateResources. Let’s start with Draw event and look at the code below:

int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; CanvasTextFormat format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; args.DrawingSession.DrawText($"Hello {i}", 200, 100, Colors.Green, format); }

In this event handler we used DrawText method to print text. You can find lots of different methods inside CanvasDrawingSession class and it’s easy to use. Pay special attention that I injected integer variable to the output string. Thanks to this variable we can see when our event handler works. Just run the application and try to work with the window for some time. You will see that Draw event fires when it’s needed for Windows to redraw the window. So, if you change window size your counter will increase but if you don’t touch widow at all the counter will remain the same.


That’s why CanvasControl works fine for “static” content.

The second important event for CanvasControl is CreateResources event. Let’s look at our code again and you can see that the application creates CanvasTextFormat object each time when Draw event handler is invoked. Of course, this object is not very complex but in case of real scenarios developers need to make lots of objects first before they can start drawing and additionally developers should guarantee that all objects will be created before event handler is invoked. There are two ways to initialize all needed objects: assign Draw event handler dynamically (right after initialization methods) or use CreateResources event handler. The second method is more straightforward and implements some stuff for asynchronous programming.

Let’s modify our XAML page:

<canvas:CanvasControl Draw="CanvasControl_Draw" CreateResources="CanvasControl_CreateResources"></canvas:CanvasControl>

And here is code:

CanvasLinearGradientBrush brush; CanvasTextFormat format; private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { brush = new CanvasLinearGradientBrush(sender, Colors.Red, Colors.Green); brush.StartPoint = new Vector2(50, 50); brush.EndPoint = new Vector2(300, 300); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); }

You can see that I used CanvasControl_CreateResources method to make a brush for my text.


Using CreateResource event handler you can guarantee that Draw event will not be fired up to the event handler is completed.

In the previous example we used synchronous event handler for CreateResource method but even for simple image loading action you need to call asynchronous APIs. Of course advanced C# developers will add async keyword before the event handler signature but this approach doesn’t work for CreateResources event handler. Instead of async keyword you should use the following approach:

CanvasImageBrush brush; CanvasTextFormat format; private void CanvasControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); } async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { brush = new CanvasImageBrush(sender); brush.Image= await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); }

You can see that we used parameter of event handler to call TrackAsyncAction method and this method can get async method as a parameter.

Ok. Thanks to CanvasControl we can draw “static” content and it’s fine for many scenarios. For example, you can use this control to apply effects to images, you can create graphs or high performance text rendering application. But you cannot use CanvasControl for developing simple 2D games or similar applications which should present “dynamic” content. In order to make it, Win2D provides another control: CanvasAnimatedControl.

We can use almost the same code, slightly modifying it:

<canvas:CanvasAnimatedControl Draw="CanvasAnimatedControl_Draw" CreateResources="CanvasAnimatedControl_CreateResources"></canvas:CanvasAnimatedControl> CanvasImageBrush brush; CanvasTextFormat format; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender) { brush = new CanvasImageBrush(sender); brush.Image= await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); format = new CanvasTextFormat() { FontSize = 96, FontWeight = FontWeights.Bold }; } int i = 0; private void CanvasAnimatedControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); } private void CanvasAnimatedControl_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

You can see the same text but counter will increase very fast (every 16.6 ms or 60 steps per second). So, CanvasAnimatedControl is better to create a large number of dynamic objects that are flying, firing, jumping etc. Of course, it’s not enough to have just Draw method because in real games you need to guarantee timing and have the same speed on all devices. So, a game loop is more complex than a simple Draw method. But developers of Win2D know about it and you can find some more events and useful properties in CanvasAnimatedControl class.

Let’s review those properties and events slightly modifying the previous Draw even handler:

private void CanvasAnimatedControl_Draw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args) { i++; args.DrawingSession.DrawText($"Hello {i}", 50, 50, brush, format); sender.Paused = true; }

You can see that we used Paused property to make pause in our game loop. And if you don’t touch the application you can see that the counter is frozen but once you resize the window the counter will grow fast. It happens because in the pause mode draw method is called once Windows needs to redraw the window. So, it’s better to use Draw event handler only for drawing. If you need to change any data in the game loop then it is better to use Update event. Update event handler will be called before Draw method and in case of pause Update event handler will be frozen.

private void CanvasAnimatedControl_Update(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedUpdateEventArgs args) { i++; }

In general, Draw+Update event handlers should be called every 16.6 ms but if you have a slow device and running timeframe is greater, Update call may be passed. So, you can see several Draw calls before Update call. It allows saving same speed of the game but you can see some drawing problems. If it happens not very often it’s not very critical but in some cases you can decrease the elapsed time for each step (for example, 30 frames per second). You can easily do it using TargetElapsedTime property.

Additionally, you can use events like GameLoopStarting and GameLoopStopped. These events fire before and after the game loop and can be used for scene initialization and for destroying all objects from memory respectively.

Pay special attention that all event handlers fire in separate gaming loop. So, any actions there will not block interface thread. But developers should think how to pass the data to the gaming thread from the interface one. The best way is calling RunOnGameLoopThreadAsync method from the interface thread:

await myCanvas.RunOnGameLoopThreadAsync(()=> {/*call something here*/});

The last control in Microsoft.Graphics.Canvas.UI.Xaml namespace is CanvasSwapChainPanel. If you know something about game development you should have heard about the swap chains. The main idea is have two or more buffers (pages) for your game. The first page you use for presenting an updated scene on the screen while updating the second one behind the scene. You should not use CanvasSwapChainPanel class or CanvasSwapChain with CanvasAnimatedControl because the last one uses swap chains internally. But if you want to implement your own CanvasAnimatedControl or a similar control you can use both classes.

var swapChain = new CanvasSwapChain(device, width, height, dpi); swapChainPanel.SwapChain = swapChain; //draw swapChain.Present();

Ok, right now we have some knowledge how to draw something and what are the differences between controls there. So, it’s time to talk about other useful classes and I am going to start with image effects.

Image effect is the most growing category in Win2D and just several days ago they added 10 more effects but we are still waiting for some classes, which help to create our own custom effects. In any case Win2D API already contains more than 50 effects, so, you definitely can find some useful filters there. Here is an example how to apply two effects to the same image:

GrayscaleEffect effect; GaussianBlurEffect blurEffect; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { effect = new GrayscaleEffect(); var bitmap=await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); effect.Source = bitmap; blurEffect = new GaussianBlurEffect(); blurEffect.BlurAmount = 5; blurEffect.Source = effect; } private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(blurEffect); } private void myCanvas_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

In this example I used blur and grayscale filters. Since I don’t have any other logic I used CreateResources event handler.


If you use the same effect for the same image you can simply apply this effect in advance and reuse it later. But in many cases you need to build more complex objects which should contain not just effect but some drawing etc. In this case you can use CanvasCommandList class in order to prepare and preserve your object for future use. I just slightly modified the previous example:

GrayscaleEffect effect; GaussianBlurEffect blurEffect; CanvasCommandList cl; async Task CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender) { cl = new CanvasCommandList(sender); using (CanvasDrawingSession clds = cl.CreateDrawingSession()) { effect = new GrayscaleEffect(); var bitmap = await CanvasBitmap.LoadAsync(sender, "Assets/drone.jpg"); effect.Source = bitmap; blurEffect = new GaussianBlurEffect(); blurEffect.BlurAmount = 5; blurEffect.Source = effect; clds.DrawImage(blurEffect); } } private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { args.DrawingSession.DrawImage(cl); } private void myCanvas_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args) { args.TrackAsyncAction(CreateResources(sender).AsAsyncAction()); }

In this example we created our own CanvasDrawingSession and used it to draw all needed objects and to apply filters there. Right after that we destroyed CanvasDrawingSession and preserved CanvasCommandList for future use (making global reference on it). Thanks to this approach you can create all complex objects in advance and later draw them as images.

When I told about image effects I didn’t mention geometry and text but you can apply effects to these entities as well. In order to do in you need to use CanvasRenderTarget class for converting vector data to pixels:

private void myCanvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args) { var myBitmap = new CanvasRenderTarget(sender, 300, 300); using (var ds = myBitmap.CreateDrawingSession()) { ds.DrawText("Hello", 0, 0, Colors.Green, new CanvasTextFormat() {FontSize=96, FontWeight=FontWeights.Bold }); } var blur = new GaussianBlurEffect { BlurAmount = 10, Source = myBitmap }; args.DrawingSession.DrawImage(blur); }

Running this code you will see the following window:


I think this is enough for the first look at Win2D. I missed lots of classes that help to work outside XAML or allow working with images pixel by pixel but I hope that it’s easy to understand using documentation because Win2D is easy.

Written by Sergiy Baydachnyy

08/04/2015 at 1:40 AM

Arduino shield for Raspberry Pi 2 or How to solve problems with PWM, analog input and not burn down the apartment with a soldering iron

with one comment

I have already published some posts where I told about Raspberry, Arduino and other boards as about boards for your own prototypes. Using these boards you can easily create something before you invite real engineers, who will make a custom board for you based on your needs. And it’s clear that all existing boards have some limitations because it’s simply not possible to create something universal that can satisfy everybody (something small, Windows 10 powered, with 60 analog pins, WiFi on board and what will not require much power). That’s why you can find lots of different micro boards on the market and Microsoft published general requirement for supported hardware but doesn’t focus on specific boards. So, once you make a prototype using available hardware you may start to think about a board which implements all needed features.

But previous paragraph doesn’t answer the question: how to create a prototype using Windows 10 IoT Core and using available boards on the market such as Raspberry Pi 2 if I still cannot use PWM, Analog signals and even some type of digital signals (pulseIn implementation)? The short answer is: keep calm and think about different boards as just a different type of brain.

I am not so strong in biology but I like to catch crabs. If you cook a crab, try to find the brain inside. Frankly speaking, I am not sure if it’s there but according to rumors in Internet it exists. In any case, if somebody asks me to implement a crab, I think that I will use just several capacitors, sensors and the simplest transistors but I will not use any CPUs at all. It’s a simple binary shifter: move all type while food sensor send low signal and change the direction if too much light (light sensor is sending low signal) is available (just go deeper). In Ukraine I keep some hamsters. I am sure that they have brain and I think that ATMega 328P-PU (Arduino Uno chip) will work fine for hamster implementation. In case of dogs it’s better to have something more advanced, faster and with ability to run some scenarios in background – I think that ARM Cortex A7 CPU should be good for this task.

So, select the brain you need. Pay special attention that the same things can have different types of brain due to different number of features. For example, I have a dream to build a drone that will able to find and destroy other drones. Of course, I need a way to use OpenCV, to implement lots of different algorithms etc. In my case, ARM Cortex A7 is must. But if you want to implement a simple RC drone and use CPU just for stabilization algorithm – ATMega will work much better.

Ok. You decided to use Cortex A7 CPU and found Raspberry PI 2 on the market which supports Windows 10 IoT Core. Thanks to Windows 10 I can develop my software very quickly using well known APIs and tools (like Visual Studio). Let’s imagine that you want to build the same drone which will intercept other drones. Of course, it’s easy to use camera, OpenCV and other technologies but stabilization algorithms should be there as well. You need a way to use PWM in order to power brushless motors, read digital signals from RC controller (like manual pilot system etc.). So, we just returned to the initial question: where is PWM…?

Raspberry Pi 2 doesn’t support software PWM. Of course, you can emulate it using software but quality of this emulation will be low and I think that the drone will be self-destructed during the first flight. But I still don’t understand why you don’t ask me about other features which are not available for Raspberry: where is embedded gyroscope? where is embedded WiFi? Where is embedded toaster?

Usually, if you need some sensors you simply buy and attach them to the board. Using I2C, SPI, Serial, you can communicate with all external stuff and implement that you need. So, if you need PWM or analog input, simply attach it.

BTW: By accident I found a Raspberry shield for copters. It’s expensive but it existsSmile

I made some research and even published the post about analog input for Raspberry but finally I decided that the best solution for PWM, Analog and digital inputs is Arduino. It was adopted by huge number of developers and it’s easy to find how to implement you code which should work with particular external sensors, shields etc. Of course, Raspberry PI and Arduino board have different form factors and Arduino board cannot be stacked on Raspberry, so I decided to build my own Arduino from scratch and build it like a shield for Raspberry.

Visiting which is physically located in Vancouver Island I bought the following things:

· Raspberry Proto Strip Board

· Stacking Header

· ATMega 328P-PU with bootloader (you can buy it without bootloader but you need another Arduino to flash bootloader there)

· 16Mhz crystal

· Some 22 pF capacitors, 0.1uF capacitors and one 10uF capacitor

Additionally, you need to make sure that you have different resistors (at least 10 kOhm and 220 Ohm) at least one led, a button and Serial to USB converter. In case of a converter you need to make sure that it has DTR pin (not just RX and TX) because I have a converter which has CTS pins, so I bought a new oneL

Finally, I spent around 20 Canadian dollars for components. I believe that I could have bought all this things for 10-15 dollars but I am not ready to wait a month for a package from China. In case of BC Robotics I got all these things in 48 hours.

On the next step you need to find a schema how to build own Arduino from scratch. I used this one: I decided to use Protected Shrimp but I simply removed the button from the circuit in order to save some space.

Just one advice there: assemble everything using a breadboard because Raspberry Proto Strip Board has similar architecture. Once you have tested your circuit it’s possible to move all components to the strip board one by one.

In 30 minutes I got this:


Now you can use USB to Serial in order to apply all needed software to your Arduino. It depends on the method you select to make a connection between Arduino and Raspberry. For example, you can use StandardFirmata sketch, which is installed with Arduino SDK and you can use I2C or Serial communications.

In case of my drone, probably, I will create my own software for Arduino because I want to implement all stabilization algorithms there and I have another important tasks for Raspberry. Because I discovered some problems with serial pins on Raspberry + Windows 10 (you still can use USB to Serial converter but….) I decided to connect Raspberry and Arduino I2C pins using simple wires. Once I select the right communication protocol I will use soldering iron to fix connection between Raspberry and Arduino.

Finally, I have ordered one more Strip Board to make one more shield with all needed sensors which will be connected to Arduino. And right after that I may forget about hardware and pay all my attention to software where I will use C#, Universal Windows Platform and Visual Studio – all things that I like!

In summary I want to emphasize two things:

· There are no problems with specific hardware features – just do it!

· If I decide to create a commercial version of my drone, I will hire some engineers and ask them to make my own board which will be ready for Windows 10 IoT core and will contain all needed sensors.

Written by Sergiy Baydachnyy

08/03/2015 at 4:20 AM

Posted in IoT, Windows 10

Tagged with

UWP: New Controls (part 5 – Media)

leave a comment »

Of course, the existing Media controls are not new but I cannot overlook them due to number of new features there. I have developed lots of applications which work with video and I know about disadvantages of Media controls in Windows 8.x like:

· Problem with adaptive streaming – in order to start working with adaptive streaming you needed to use external libraries like Player Framework and Smooth Streaming SDK because Windows 8.x SDK doesn’t support embedded features for adaptive streaming. Even if you use these libraries you will get support for Smooth Streaming only;

· No support of existing formats for closed captions – Windows 8.x SDK doesn’t support closed captions at all. SMPTE-TT and TTML were introduced in Player Framework SDK only;

· No way to change template for existing media player control – Windows 8.x supports SystemMediaTransportControls but there were not many ways to change something. So, you had to design your own player from scratch or use existing player from Player Framework with less ability to change anything there;

Let’s see how Microsoft fixed all these disadvantages in Universal Windows Platform.

Adaptive Streaming

HTTP Live Streaming (HLS), Dynamic Adaptive Streaming over HTTP (DASH) and Microsoft Smooth Streaming are the most popular technologies for adaptive streaming. New MediaElement control supports all of them.

If you want to test how it works it’s better to use Azure account (you can use trial) and create Media Service instance there. Media Service supports dynamic packaging, so you can upload your video there and encode it using one of profiles which are ready for adaptive streaming.


Pay special attention that you need to create at least one streaming unit. Once video is encoded, thanks to dynamic packaging, you can stream it using any format that I mentioned previously (HLS, Dash, Smooth).

Let’s test, how to work DASH. In order to do it you need just add MediaElement to XAML page:

<MediaElement Name="media" AreTransportControlsEnabled="True" />

In order to create adaptive media source you can use AdaptiveMediaSource class like this:

AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(new Uri("", UriKind.Absolute)); if (result.Status == AdaptiveMediaSourceCreationStatus.Success) { var astream = result.MediaSource; media.SetMediaStreamSource(astream); }

My video works fine and thanks to MediaTransportControls I have great interface for my media player:



If you want to add closed captions it’s easy to do with new controls as well. Just use the following code to associate TTM file with existing adaptive stream:

AdaptiveMediaSourceCreationResult result = await AdaptiveMediaSource.CreateFromUriAsync(new Uri("", UriKind.Absolute)); if (result.Status == AdaptiveMediaSourceCreationStatus.Success) { var astream = result.MediaSource; var ttmSource = TimedTextSource.CreateFromUri(new Uri("ms-appx:///assets/captions.ttm")); var mediaSource=MediaSource.CreateFromAdaptiveMediaSource(astream); mediaSource.ExternalTimedTextSources.Add(ttmSource); var mediaElement = new MediaPlaybackItem(mediaSource); media.SetPlaybackSource(mediaElement); }

You can see that we use TimedTextSource class to create source based on file with captions. In order to associate the captions with media source we used MediaSource class and MediaPlaybackItem class to prepare source for MediaElement.

Template for Media

Starting with Windows 10 the MediaTransportControls class has its own states and a template according to modern design. It allows to change anything there by modifying the existing XAML template. So you should not create buttons from scratch, implement logic etc. There are three ways to get existing template for MediaTransportControl: visit MSDN, find generic.xaml file on your computer or use Blend.

Because I have written this post before release of Windows 10 SDK there was no information on MSDN but I hope that you can find it right after release.

Generic.xaml file you can find using the following path C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10069.0\Generic. Just open generic.xaml and find template for MediaTransportControls there.

Finally, you can extract template using Blend tool. I would like recommend this way because it’s easy not just to create copy of template but to modify it as well. In order to extract template for MediaTransportControls you need to create a new project (or open existing) in Blend and add MediaTransportControls to a page. Using context menu select Edit Template -> Edit a Copy menu item.


Blend will propose to select location and name for new style. So, select it and click OK.


Right after it you can open XAML and modify new template there or use powerful editor in Blend to see and modify everything there


Written by Sergiy Baydachnyy

07/31/2015 at 8:28 PM

UWP: Extensions and ApiInformation

leave a comment »

Universal Windows Platform allows to build universal applications for all devices which run Windows 10. I have already published several posts about new controls which allow to create universal interfaces for different screen sizes and resolutions. But what about device-specific features? For example: Raspberry Pi has set of pins which are not available for phone and tablets; you can use desktops and laptops in order to print something directly from your application but this functionality is not available for phones; lots of phones support vibration what is very uncommon for laptops etc. That’s why all contracts with device-specific functionality were moved to special libraries called extensions.

You can include existing extensions to your project using Add Reference dialog and open Extensions tabs. Today you can find three most important extensions there like Mobile Extension, Desktop Extension and IoT Extension.


Of course you might see more extensions soon. For example, Microsoft might publish some extensions for Xbox and Hololens but you will be able to create your own for own Windows 10 devices.

If you want to see all contracts which were included to the extension, you can open the manifest file for the selected extension and check all contracts there. For example, you can find the IoT manifest using the following folder C:\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsIoT\10.0.10069.0 and manifest looks like

<?xml version="1.0" encoding="utf-8"?> <FileList TargetPlatform="UAP" TargetPlatformMinVersion="" TargetPlatformVersion="10.0.10069.0" SDKType="Platform" DisplayName="Windows IoT Extension SDK" AppliesTo="WindowsAppContainer" MinVSVersion="14.0" ProductFamilyName="Windows.IoT" SupportsMultipleVersion="Error" TargetFramework=".NETCore, version=v4.5.3;" SupportPrefer32Bit="True" MoreInfo=""> <ContainedApiContracts> <ApiContract name="Windows.Devices.DevicesLowLevelContract" version=""/> <ApiContract name="Windows.System.SystemManagementContract" version=""/> </ContainedApiContracts> </FileList>

So, right now there are two contracts only and you can find all classes there using Object Browser in the Visual Studio.

I already published how to use IoT extensions for Raspberry Pi 2. So, in this article I want to talk more about how to implement universal approach even if you add an extension.

The main idea of Universal Windows Platform is to give a way to create just one application and one binary for all devices. But what happens when we add an extension? Should we recompile our application for different platforms with this extension and without the extension? The answer is No.

Extensions are designed in the way when you can continue to run your code on a platform which doesn’t support extensions which you have included to your project. But if you try to call methods and create objects based on classes from the extensions, these calls will generate runtime exception.

That’s why you need to check in runtime if selected extension is available on the platform. Of course, you should not do it in exception handler. It’s better to adopt the interface of your application for the specific device rather than notify users about some unsupported feature when the application is running. So, developers need to have better tool to check availability of contract and Microsoft implemented all needed features in ApiInformation class.

ApiInformation is located in Windows.Foundation.Metadata namespace and contains several static methods like IsApiContractPresent, IsEventPresent, IsMethodPresent etc.

So, if you want to check, if GPIO is available, you can use the following code:

if (ApiInformation.IsApiContractPresent("Windows.Devices.DevicesLowLevelContract", 1)) { //doing something with GPIO }

Pay special attention that IsApiContractPresent requires two parameters. The second one is major version (you can use minor version as well – third parameter). This parameter is needed because Microsoft can update some of contracts and you can target specific version(s).

The code above doesn’t mean that you need to create hundreds of if blocks if you include one or several contracts. It’s better to create a custom trigger based on this information and implement several visual states.

Written by Sergiy Baydachnyy

07/27/2015 at 6:50 PM

UWP: New Controls (part 4 – Inking)

leave a comment »

One more powerful control in Universal Windows Platform is InkCanvas. Thanks to this control you can enable inking anywhere in your application and you can use not just stylus but fingers and mouse as well. So, thanks to this feature you can bring inking functionality to any device based on Windows 10.

To enable inking you need to start with InkCanvas element and place it inside any container like StackPanel, Grid, etc. Like other UI controls based on FrameworkElement, InkCanvas contains a bunch of properties but in the simplest case you do not have to declare anything:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <InkCanvas Name="ink"></InkCanvas> </Grid>

In this case InkCanvas will fill all space inside the container and you can start make your notes or paint something. Pay special attention that by default InkCanvas accepts input from stylus (pen) only. So, if you want to use fingers or mouse you need to implement the following code:

ink.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse|CoreInputDeviceTypes.Touch;

In this code we are using the second important object – InkPresenter. InkCanvas is just a control which contains just one inking property – reference to InkPresenter but InkPresenter contains all information about input methods and lots of different settings there including collection of strokes. You cannot create InkPresenter directly but you can get reference to the object of this class using InkPresenter property of InkCanvas. Frankly speaking InkCanvas doesn’t contain any other properties or methods related to inking. But we still have something to discuss about InkCanvas and the most important question there is how to enable inking anywhere because usually you need to enable inking for images, videos, text rather than using inking inside a blank container. Let’s add several controls to the container and see what happens there.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <InkCanvas Name="ink"></InkCanvas> <StackPanel> <TextBlock Text="Hello. Here is some text." Margin="20"></TextBlock> <Button Content="Click me" Margin="20"></Button> </StackPanel> </Grid>

If you run this code you will see that all controls work fine and you can make any notes there.


In our example we placed InkCanvas behind other controls but if you swap StackPanel and InkCanvas you can see that InkCanvas is placed above StackPanel and controls like Button don’t work at all. You can resolve it thanks to Canvas.ZIndex property.

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <StackPanel Canvas.ZIndex="1"> <TextBlock Text="Hello. Here is some text." Margin="20"></TextBlock> <Button Content="Click me" Margin="20"></Button> </StackPanel> <InkCanvas Name="ink" ></InkCanvas> </Grid>

Let’s talk about settings of InkPresenter and how to make different effects there. It’s all around InkDrawingAttributes class. You simply need to create an object of this class and set different properties like Color, PenTip, Size etc.

InkDrawingAttributes attr = new InkDrawingAttributes(); attr.Color = Colors.Red; attr.IgnorePressure = true; attr.PenTip = PenTipShape.Circle; attr.Size = new Size(4, 10); attr.PenTipTransform = Matrix3x2.CreateRotation((float)(70 * Math.PI / 180)); ink.InkPresenter.UpdateDefaultDrawingAttributes(attr);

Code below shows how to use InkDrawingAttributes. In order to update attributes you need to call UpdateDefaultDrawingAttributes and pass InkDrawingAttributes object there. In code below I used PenTipTransform property as well. This is a very interesting property which allows to apply transformation to pin shape and get more natural look for strokes thanks to different height of strokes based on direction of pen (moving direction/angle).


You can check the image below where I tried to paint symbol “f” and you can see that the image contains strokes with different height. In fact I used the same settings but this effect was applied thanks to PenTipTransform.

Finally, you can paint anything but how can you erase some strokes if you make anything wrong? In order to do it you need to change mode of InkPresenter:

ink.InkPresenter.InputProcessingConfiguration.Mode = InkInputProcessingMode.Erasing;

The next important class which is related to inking is InkStroke. Anything what you paint on InkCanvas consists of InkStroke. In order to get access to functionality around InkStroke objects you can use StrokeContainer property of InkPresenter. Thanks to this property you can save existing strokes to file, add new strokes, get access to selected strokes etc. So, if you want to implement any functionality around strokes then StrokeContainer is your friend. Of course the most popular methods there are LoadAsync and SaveAsync.

Lots of applications require recognition functionality as well. In order to recognize text based on hand writing you can use InkRecognizerContainer class. In the simplest way you can use this class like this:

InkRecognizerContainer container = new InkRecognizerContainer(); var result=await container.RecognizeAsync(ink.InkPresenter.StrokeContainer, InkRecognitionTarget.All); string s=result[0].GetTextCandidates()[0];

This code will use default recognizer and convert the first text candidate from the list to text. Of course it’s not enough for more complex scenarios. For example, I spend 10 years at school to train my handwriting for Russian and Ukrainian but not for English. So, when I am trying to write something in English usually I can find the right result on the second or third place in the list of text candidates. Additionally, I can have several recognizers on my computer.

So, it’s better to allow to select the right recognizer. You can simply use SetDefaultRecognizer and GetRecognizers of InkRecognizerContainer object to do it. In case of non-native English writers I am not sure that you need to present full list of possible results. It’s better to ask users to setup recognizer using system settings. For example, I can setup the default recognizer to adopt to my writing style if I select “write each character separately” and make some “teach” settings:


At the end of the post I want to draw your attention to Ink Toolbar control. It’s not a default UWP control and you need to install this control separately. Once you install the control it will be available in Extension tab of Add Reference dialog (close and open Visual Studio after installation) and it’s ready to use. You just need to add reference to the library:


Find a place for the control and make reference to the existing InkCanvas:

<InkCanvas Name="ink" ></InkCanvas> <ink:InkToolbar TargetInkCanvas="{x:Bind ink}" VerticalAlignment="Top" HorizontalAlignment="Right"></ink:InkToolbar>

Below you can see the control itself which generates our code:


Written by Sergiy Baydachnyy

07/27/2015 at 6:45 PM

UWP: New Controls (part 3 – Maps)

leave a comment »

In this post I am going to talk about maps in Universal Windows Platform applications. And it’s better to start with the answer to the question that developers asked me many times: when will offline maps be available for Windows applications?

Starting with Windows 10 offline maps are available not just for phones but for desktops, laptops, tablets etc. User can visit Settings window and download all needed maps there. Once maps are downloaded the existing map control will use them by default.


It’s really cool because I can use my Windows 10 devices anywhere in order find addresses, the right direction etc. and you can access? all these things directly from your application.

But offline maps are not the single feature of new Windows 10 maps. Let’s look at other features there:

· Unified platform – since Windows 10 you should not use several services like Here or Bing Maps for different tasks (or different services on different devices). All services are available under the same umbrella and can be used for any UWP applications;

· Adaptive interface – existing Maps application works fine on all devices. You can use touch, pen or mouse as well as use different screen sizes. The same we can say about MapControl which is available for developers;

· 2D view with business and traffic information – existing maps support all common features for 2D maps like different views, traffic information (you can on or off it), provide information about business locations and transit;

· Location – existing Maps application allows to find and display user location. Using Windows.Devices.Geolocation API you can find user location in your application in order to provide better user experience and implement lots of different tasks;

· External elements – developers can place own icons, rectangles, polygons and even XAML controls on maps. It allows to customize existing maps and extend the number of possible scenarios;

· Geofence – Geofencing API allows to notify application if user arrives to the defined area;

· Routing – developers can use Maps services that can calculate route to selected destination using different methods there (driving, walking);

· StreetSide – new functionality which allows to get images of the selected area to display it inside the interface. It’s very useful if user wants to understand what the selected area looks like;

· 3D views – one more new functionality which is available for developers starting with Windows 10: right now you can show maps not just in 2D but in 3D view modes. If 3D view is available for the selected area you can implement the same set of features like in standard Maps application;

It’s time to talk how to use maps in your applications. You have two ways there: you can redirect some user requests to the existing Maps application or you can integrate maps directly to your application.

If you are going to utilize existing Maps application you can redirect user to it using Launcher class. This class contains LaunchUriAsync static method which allows to open an external application using information from Uri. For example, if you use “http://….” in your uri then Launcher will open web browser but in case of Maps you need to start your uri with bingmaps:. Of course, it’s not enough and you need to pass some parameters using your uri. The full list of possible parameters you can find using the following link. For example, this code will open Maps application in move center to North Vancouver and zoom the map to level 14:

await Launcher.LaunchUriAsync(new Uri("bingmaps:?lvl=14&rpt=adr.North%20Vancouver%20BC"));

In order to start working with maps in your application you need to get “access key” visiting Maps Dev Center. You can select Trial key or Basic key based on your needs. Right after Windows 10 is released you will be able to find Universal Application in the list of possible applications but right now there is still no information about Windows 10. In any case you cannot publish Windows 10 applications right now (several days left), so you can use maps without key. It works fine but you will see the message that MapServiceToken is not specified and you cannot publish your application without MapServiceToken.

Once Windows 10 is available you can create Basic key for your universal application using the portal:


In order to start working with maps in your application you need to use three namespaces – Windows.UI.Xaml.Controls.Maps, Windows.Devices.Geolocation and Windows.Services.Maps and one control – MapControl. The first namespace contains MapControl itself and several classes which allows to place something on maps, setup camera and styles, prepare street view. The second namespace allows to get user location and contains Geofencing API as well. And the last one supports several utility classes which allows to find location by address, calculate route etc.

Because MapControl is not in default XAML namespaces you need to add a new namespace to XAML file:


And you are ready to use MapControl:

<maps:MapControl MapServiceToken="..."/>

Right now we know how to add maps to your application and it’s time to see some tasks there.

Let’s start with basic functionality like how to center map, zoom map etc. Let’s have a look at the following code:

maps.ZoomLevel = 14; maps.Center = (await MapLocationFinder.FindLocationsAsync("North Vancouver, BC", null)).Locations[0].Point;

In this code we use reference to MapControl in order to assign two properties ZoomLevel and Center. Of course, in case of ZoomLevel you should not do anything special but if you want to center your map based on address you need to use map services – MapLocationFinder in this case. In my example I used FindLocationsAsync method and assigned the first location from the list to the Center property.

In order to apply 3D view to the maps you simply need to use Style attribute. It’s somewhat confusing because Style attributes exists for all UI controls and that can have different meaning.

<maps:MapControl Name="maps" Style="Aerial3D"/>

Of course, in case of the 3D View, it’s better to change default angle for map camera. You can do it usingthe static method of MapScene class called CreateFromLocationAndRadius. Thanks to this method you can create a scene using radius (meters), zoom level and radius (degrees). Once you have MapScene object you need to use TrySetSceneAsync method to apply the scene:

await maps.TrySetSceneAsync(MapScene.CreateFromLocationAndRadius((await MapLocationFinder.FindLocationsAsync("Vancouver Downtown, BC", null)).Locations[0].Point,500,90,60));

If you run my code you will see center of Vancouver in 3D:


So, applying 3D view is easy. The same works for the StreetView functionality. If you want to use the street view you need just two lines of code:

StreetsidePanorama panorama=await StreetsidePanorama.FindNearbyAsync((await MapLocationFinder.FindLocationsAsync("Vancouver Downtown, BC", null)).Locations[0].Point); maps.CustomExperience = new StreetsideExperience(panorama);

If you run this code you can see something like this:


Of course, existing maps show lots of different information but if you integrate maps to your application, probably, you want to add your own objects to maps.

The simplest objects which you can add to the maps are MapIcon, MapPolygon and MapPolyline. For example, if you want to add an icon to the maps you can run the following code:

MapIcon mapIcon = new MapIcon(); mapIcon.Location = maps.Center; mapIcon.NormalizedAnchorPoint = new Point(0.5, 1.0); mapIcon.Image = RandomAccessStreamReference.CreateFromUri(new Uri("ms-appx:///Assets/weather.png")); mapIcon.ZIndex = 0; maps.MapElements.Add(mapIcon);

You can use this code to place weather icons in the area, points of interest etc.

Additionally you can add XAML controls to the maps. In this case you need to use Children collection instead of MapElements as before. But it’s not enough to add XAML UI control, you need to place the control to the right position on the maps. In order to do it you can use the SetLocation method of the MapControl class. This method has two parameters: reference to added UI control and location.

Therefore you can see that the current version of MapControl is very powerful and supports lots of features. It’s even possible to write a separate book just about this control. If you want to know more, the best starting point for you is Bing portal for developers. The portal contains lots of examples and information how to use Bing maps from JavaScript or in applications for alternative platforms.

Written by Sergiy Baydachnyy

07/20/2015 at 7:21 PM

UWP: 3D Transformation

with one comment

If you develop applications for Windows Phone 8.1 or Windows 8.1 you can use PlaneProjection class which allows applying 3D transformations to any UI elements. But PlaneProjection is very limited and provides only a way to make rotation. If you want to apply more complex 3D transformations you need to use MatrixTransform and implement your own math algorithms.

But starting with Windows 10 you have a way to make more complex 3D transforms using new classes like PerspectiveTransform3D and CompositeTransform3D. Let’s look at the following code:

<RelativePanel HorizontalAlignment="Center"> <RelativePanel.Transform3D> <PerspectiveTransform3D></PerspectiveTransform3D> </RelativePanel.Transform3D> <Image Source="Assets\drone.jpg" Width="400" Name="image"> <Image.Transform3D> <CompositeTransform3D CenterX="200" CenterY="100" RotationX="{x:Bind sliderX.Value,Mode=OneWay}" RotationY="{x:Bind sliderY.Value,Mode=OneWay}" RotationZ="{x:Bind sliderZ.Value,Mode=OneWay}"> </CompositeTransform3D> </Image.Transform3D> </Image> <Slider Maximum="360" RelativePanel.Below="image" Name="sliderX" Width="400" Margin="0,10,0,10"></Slider> <Slider Maximum="360" RelativePanel.Below="sliderX" Name="sliderY" Width="400" Margin="0,10,0,10"></Slider> <Slider Maximum="360" RelativePanel.Below="sliderY" Name="sliderZ" Width="400" Margin="0,10,0,10"></Slider> </RelativePanel>

If you execute the code you will see the screen below where you can rotate an image using three sliders:


Frankly speaking you would be able to make something like it using PlaneProjection as well but with this example we can understand syntax for new elements.

First of all you need to use PerspectiveTransform3D element and assign it to Transform3D property which is available for all UI elements. PerspectiveTransform3D allows to declare a common view port for all child elements. So you should think about it as about a perspective camera. You can move the camera using OffsetX and OffsetY properties but this movement will not affect position of your control inside the container – it just affects transformations because you have the same view port and any camera movement will add an angle which will affect projection only. PerspectiveTransform3D has Depth property as well which declares distance between camera and Z=0 plane. By default Depth is 1000 but you can change it and it affects transformations only as well. Frankly speaking I found that if you change Depth you will see unpredictable effects.

Once you apply PerspectiveTransform3D to any container you can use CompositeTransform3D to apply any transformations to elements inside view port. You can scale, translate and rotate UI elements.

At the same time I discovered two disadvantages there.

First of all CompositeTransform3D allows to set the center of the transformation but it requires to use pixels. So, if I want to make transformation around the center of a control I need to calculate actual size. It’s strange because even PlaneProjection allows to set center in relative coordinates ((0.5, 0.5) – center).

The second disadvantage is a problem with correct placement of controls in the space – elements are rendered in XAML order, one by one. So, elements that are closer to each other can be placed behind elements that are not so close. MSDN recommends to use workaround (Canvas.ZIndex) but it requires to implement complex code which should change ZIndex dynamically. Additionally, there are lots of tasks when ZIndex doesn’t help. So, in the current version you cannot use these classes for more complex scenarios.

If you need to build complex 3D models I would recommend to use WebView and implement your model there using CSS 3D. Since Windows 10, WebView is based on Microsoft Edge and support preserve-3d value for 3d transformation.


Written by Sergiy Baydachnyy

07/17/2015 at 6:44 PM

Tailored views or one more way to create Universal interfaces

with one comment

If you visit what’s new for developers in Windows 10 page you can see the following sentence there:

“XAML provides new support for defining tailored views (.xaml files) that share the same code file.”

Of course this feature can be very useful because in some cases it’s not easy to create really universal pages. For example, you can adopt all controls but you need to remember that phone users usually use just one hand to work with applications. So, you need to adopt not just layout but user experience as well.

That’s why I tried to investigate what this sentence means. Looks like this feature is still in development and you will not find any docs about it but you already can test existing implementation.

In current version of UWP you already can create separate XAML for desktop and mobile pages. In order to do it you need to add a new XAML View to your project.


You can see that XAML Veiw template will create XAML page only without code behind file. Of course, it’s not enough and in order to associate a new view with page by default you need to select one of the two approaches:

· You can place the view to the same folder with the initial page and you need to call the view using the name of the initial page and add a prefix. I discovered two prefixes right now – DeviceFamily-Mobile and DeviceFamily-Desktop. I didn’t have a chance to test Xbox and I found that DeviceFamaly-IoT doesn’t work;

· You can use the same name for the view which has the page by default but you need to place the view to the special folder – DeviceFamily-Mobile or DeviceFamily-Desktop;


That’s all. If you run our application on the phone and you will have a view under DeviceFamily-Mobile rule then the view will be applied but if you didn’t implement a new view around DeviceFamily-Mobile then XAML by default will be applied. The same things work for desktop.

Pay special attention that it’s in preview now and even no docs have been published.

Written by Sergiy Baydachnyy

07/14/2015 at 4:35 AM

UWP: New Controls (part 2 – SplitView)

with one comment

Another control which allows to create adaptive interfaces is SplitView. Usually you will use this control to create menus but in fact SplitView allows to declare two panels, Pane and Content, with any content inside. Particularly the Pane panel allows to add some adaptive capabilities by supporting different display modes. The main syntax of SplitView is

<SplitView IsPaneOpen="False" DisplayMode="CompactInline" PaneBackground="Beige" OpenPaneLength="200" CompactPaneLength="30"> <SplitView.Pane> </SplitView.Pane> <SplitView.Content> </SplitView.Content> </SplitView>

Where the DisplayMode property can be set in one of the following values:

· CompactInline – Pane panel supports compact mode. When it is expanded all content will be moved in order to provide enough space for expanded panel;

· CompactOverlay – the same as the previous mode but when panel is expanded it doesn’t affect all other content because the panel will be placed above the content;

· Inline – supported in expanded mode only. If it is displayed then all other content will be moved to have enough space for the panel;

· Overlay – supported in expanded mode only. It doesn’t affect all other content because the panel will be placed above the content;

With the help of the IsPaneOpen you can define if the panel is displayed in standard mode or if the panel is expanded (or compact) in compact mode. So, if you set IsPaneOpen to false and display mode is compact then the panel will be displayed in compact mode. If you change IsPaneOpen to true then the panel will be displayed in expanded mode.

So, you can see that SplitView doesn’t have anything related to menus but you can easily place something like ListView inside and declare menu items there. Design the menu items in the way that users can see only icons in the compact mode and all of the content in expanded mode, and implement VisualStateManager which changes DisplayMode and IsPaneOpen properties in runtime.

I would would advise to follow these recommendations in order to design your own menu:

· Implement three states for your menu: Expanded, Compact and UltraCompact for different screen sizes. If you have enough space you can show the Pane in expanded mode without any problems but if you have less space you can show just icons in compact mode. Finally if you don’t have room at all (phone in portrait orientation) you should activate UltraCompact state and hide your Pane completely;

· In Compact and UltraCompact states add a bullet button above the menu which opens the Pane using Overlay modes. So, you will be able to open the menu even in UltraCompact mode when menu is hidden;


· Use ListView control for menu;

So your VisualStateManager can look like this (CompactInline as default and IsPaneOpen is True):

<VisualState x:Name="Expanded"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="900"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="Compact"> <VisualState.Setters> <Setter Value="False" Target="splitView.IsPaneOpen"></Setter> <Setter Value="CompactOverlay" Target="splitView.DisplayMode"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="500"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="UltraCompact"> <VisualState.Setters> <Setter Value="False" Target="splitView.IsPaneOpen"></Setter> <Setter Value="Overlay" Target="splitView.DisplayMode"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState>

If you implement a bullet button you need to add logic which allows to expand menu as well. You can implement all logic inside code behind or you can try to create two more states and your own triggers there.

Written by Sergiy Baydachnyy

07/14/2015 at 4:33 AM

UWP: New Controls (part 1 – RelativePanel)

with one comment

In the next posts I am going to discuss new controls which are available for Windows 10 developers. And today I am going to start with a new layout control RelativePanel. For better understanding of the control I will start my post with a short example:

<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <TextBlock Text="This is a header" Grid.ColumnSpan="2" Style="{ThemeResource HeaderTextBlockStyle}"></TextBlock> <Image MaxWidth="800" Grid.Row="1" Source="Assets\drone.jpg" VerticalAlignment="Top"></Image> <TextBlock Text="This is a text about drones." Margin="10,0,10,0" TextWrapping="Wrap" Grid.Column="1" Grid.Row="1"></TextBlock> </Grid>

In this example I implemented a simple layout which uses Grid element to place two text blocks and an image. So, if you run this code you can see something like this:


But there is a problem, Windows 10 allows to change size of windows and additionally I can run this application on phones. So it’s easy to see that I don’t have enough space to show image and text if I have a smaller window. Because I want to create a universal interface I should change my layout dynamically if I don’t have enough space. Probably I simply need to place the text below the image and VisualStateManager is the best way to do this. But I used Grid container which has two columns and two rows and for smaller display I need a grid with one column and three rows which is virtually impossible to manage in VisualStateManager even for my example (but the real interfaces are much more complex). That’s why when developers build universal applications for Windows 8.1 they duplicate some parts of the interface and simply work with Visibility property inside VisualStateManager.

Starting with Windows 10, developers have a chance to use the new container which allows to avoid problems with Grid – it’s RelativePanel. Let’s see the same example but inside RelativePanel control.

<RelativePanel > <TextBlock Text="This is a header" Name="header" Style="{ThemeResource HeaderTextBlockStyle}"></TextBlock> <Image Name="image" MaxWidth="800" RelativePanel.Below="header" Source="Assets\drone.jpg"></Image> <TextBlock Text="This is a text about drones." Margin="10,0,10,0" TextWrapping="Wrap" RelativePanel.AlignTopWith="image" RelativePanel.RightOf="image" Name="text"></TextBlock> </RelativePanel>

You can see that in case of RalativePanel you can declare position of embedded controls using dependency properties. Because it’s just properties, it’s easy to reformat layout using them in VisualStateManager. For example, you can use the following code to show the same interface in one row:

<VisualStateManager.VisualStateGroups> <VisualStateGroup> <VisualState x:Name="Normal"> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="900"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="Mobile"> <VisualState.Setters> <Setter Value="" Target="text.(RelativePanel.AlignTopWith)"></Setter> <Setter Value="image" Target="text.(RelativePanel.Below)"></Setter> <Setter Value="" Target="text.(RelativePanel.RightOf)"></Setter> <Setter Value="0,10,0,10" Target="text.Margin"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState> </VisualStateGroup> </VisualStateManager.VisualStateGroups>

Once the window is less than 900 pixels, the text is moved below the image. Pay special attention how to declare dependency properties in the Target attribute.

So, let’s use this powerful control, and according to my experience, Relative panel is the most popular control for creating universal interface now.

Written by Sergiy Baydachnyy

07/06/2015 at 6:59 PM