Sergiy Baydachnyy

Blog about technologies

Archive for the ‘Universal Applications’ Category

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:

clip_image002

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.

clip_image004

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.

clip_image002

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;

clip_image003

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;

clip_image002

· 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:

clip_image002

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

UWP: How to handle changes of DependencyProperty

with 2 comments

Last time we discussed how to create our own state trigger. In order to do it we made some extensions of “view model” class in order to get information about changes in state of the model. We declared a delegate and an event there and additionally we injected code which initiated external event handlers. But in many cases you cannot modify a class which you are going to use in your trigger and the class doesn’t have needed events as well. In this case you can check dependency properties there.

Starting with Windows 10 you can handle changes in dependency properties even if the class doesn’t have any special events for it. It’s possible thanks to RegisterPropertyChangedCallback (and UnregisterPropertyChangedCallback) method which was included to DependencyObject class. Thanks to this method you can provide an event handler which fires when selected DependencyProperty is changed. This method is very useful for UWP controls when you need to track changes in existing controls but we can utilize this method in our classes as well.

Let’s try to modify classes from the previous post.

public enum StateEnum { Loading, Loaded, Error } public class PageViewModel: DependencyObject { public static readonly DependencyProperty StateProperty= DependencyProperty.Register("State",typeof(StateEnum), typeof(PageViewModel),new PropertyMetadata(null)); public StateEnum State { get { return (StateEnum)GetValue(StateProperty); } set { SetValue(StateProperty, value); } } public void InitModel() { State = StateEnum.Loading; //load data State = StateEnum.Loaded; } }

You can see that I removed the delegate and the event and added a StateProperty dependency property. Right now code looks better and usually if you implement your own “view model” class you already have some dependency properties there and probably you should not change anything.

Of course, in order to work with dependency properties we use the SetValue and GetValue methods. We used standard approach there – created a wrapper property. It’s clear that all changes around DependencyProperty in UWP were implemented inside the SetValue method. It just executed all methods which were registered thanks to RegisterPropertyChangedCallback.

My state trigger will look different as well:

public class DataTrigger: StateTriggerBase { private PageViewModel model; public PageViewModel Model { get { return model; } set { model = value; model.RegisterPropertyChangedCallback(PageViewModel.StateProperty, new DependencyPropertyChangedCallback(ChangeState)); } } private void ChangeState(DependencyObject obj, DependencyProperty pr) { SetActive(model.GetValue(PageViewModel.StateProperty). ToString().Equals(StateOfModel)); } public string StateOfModel { get; set; } }

You can see that code looks better right now. Pay special attention that we use PageViewModel object to call RegisterPropertyChangedCallback method.

So, if you don’t have all needed events, check existing dependency properties and in many cases you find all that you need.

Written by Sergiy Baydachnyy

07/05/2015 at 1:50 AM

UWP: New features of Visual State Manager (part 2)

with one comment

In the previous post I told about two new features of Visual State Manager like setters and adaptive triggers and you can see that adaptive triggers are limited to screen size only. But in real applications you can change your interface based on lots of different parameters like Xbox controller availability, screen orientation, data availability etc. So, in this article I want to show how to extend existing infrastructure of adaptive triggers creating new one.

It’s hard to find an application which is not connected to Internet. But getting data from the Internet takes some time. Usually I use ProgressRing to show that getting the data is in progress and I use VisualStateManager to show or hide elements based on data availability. Usually there are three states like Loading, Loaded and Error. Of course, I needed to implement some code which change state of application based on state of “view model”. Let’s see if it’s possible to implement our own trigger which helps to avoid coding in code-behind class of my page completely.

First of all we need to check if our “view model” class is ready for triggers. It’s better to implement a property which shows current state of our model as well as an event which fires every time when model change own state. Of course, it’s better to implement base class for all view models in our application.

public enum StateEnum { Loading, Loaded, Error } public class StateChangeEventArgs:EventArgs { public StateEnum State { get; set; } } public delegate void StateChangedDelegate(object model, StateChangeEventArgs args); public class PageViewModel { public event StateChangedDelegate StateChanged; public void InitModel() { if (StateChanged != null) StateChanged.Invoke(this, new StateChangeEventArgs() { State = StateEnum.Loading }); //load data if (StateChanged != null) StateChanged.Invoke(this, new StateChangeEventArgs() { State = StateEnum.Loaded }); } }

I have implemented InitModel method as well as an example of code where we need to invoke StateChanged event. Usually you will implement this method in your own way and into inherited classes.

Once you have updated “view model” you can create object of it inside page XAML file:

<Page.Resources> <st:PageViewModel x:Name="model"></st:PageViewModel> </Page.Resources>

It’s time to create your own trigger. In order to do it you need to create a new class which inherits StateTriggerBase class. Inside the class you can declare any method and properties but you need find a place where you will call SetActive method. Thanks to this method you can activate or deactivate your trigger. For example, I implemented the following class:

public class DataTrigger: StateTriggerBase { private PageViewModel model; public PageViewModel Model { get { return model; } set { model = value; model.StateChanged += Model_StateChanged; } } public string StateOfModel { get; set; } private void Model_StateChanged(object model, StateChangeEventArgs args) { SetActive(args.State.ToString().Equals(StateOfModel)); } }

You can see that I have two properties in the class which allow to set reference to the current view model and define a state which we are going to use to activate the trigger. Once view model is initialized we will activate or deactivate the trigger using the event handler for StateChanged event.

Finally, I declared the following states:

<VisualState x:Name="Loading"> <VisualState.Setters> <Setter Target="gridView.Visibility" Value="Collapsed"></Setter> <Setter Target="progress.Visibility" Value="Visible"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <st:DataTrigger Model="{StaticResource model}" StateOfModel="Loading"></st:DataTrigger> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="Loaded"> <VisualState.Setters> <Setter Target="gridView.Visibility" Value="Visible"></Setter> <Setter Target="progress.Visibility" Value="Collapsed"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <st:DataTrigger Model="{StaticResource model}" StateOfModel="Loaded"></st:DataTrigger> </VisualState.StateTriggers> </VisualState>

It’s really cool and allows to make better implementation of MVVM pattern.

Written by Sergiy Baydachnyy

06/30/2015 at 10:46 PM

UWP: New features of Visual State Manager (part 1)

with one comment

If you are going to develop Universal Windows applications for Windows 10 you should think about adaptive interface which will successfully work on all Windows devices with different screen sizes, orientations and resolutions. As I mentioned in my previous post, Visual State Manager is a very good approach to implement adaptive interface. Visual State Managers allow to declare different states of UI with ability to change the current state in runtime. That’s why Microsoft continues to invest resources to this component and today developers can use two more features there.

Setters

If you are going to use animation to change the state you can continue to use old approach with Storyboard but in many cases animation is not needed. For example if you want to change your layout because user changed screen orientation, you need to change properties of controls very quickly. So, developers usually used ObjectAnimationUsingKeyFrame in order to make all needed changes in 0 seconds:

<Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" Storyboard.TargetProperty="Visibility"> <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/> </ObjectAnimationUsingKeyFrames> </Storyboard>

You can see that this approach is not optimal because it requires using several complex objects with many parameters to make the simple thing. That’s why a new XAML element called Setter can be very useful. For example, you can rewrite the same thing using the Setter element:

<VisualState.Setters> <Setter Target="comboBox.Visibility" Value="Collapsed"></Setter> </VisualState.Setters>

It’s much clearer. Developers need to declare a property’s name and a new value in the selected state.

If you want you can mix Setters and Storyboard inside the same state.

Adaptive triggers

Of course it’s not enough to declare all possible states – developers need to implement code which allows to change the state dynamically. For example, if you are going to change the state based on screen size, you need to implement event handler for SizeChanged event and use GoToState method of VisualStateManager class. Sometimes it’s not clear when a state should be applied. Additionally, if you have several state groups and need to combine several states, you can easily make a mistake. That’s why Microsoft implemented an infrastructure for state triggers. It allows to declare one trigger or a set of triggers inside XAML to understand which state should be applied. So, you can declare all needed rules without coding at all.

In the current version Microsoft presented just one trigger – AdaptiveTrigger, but I hope that in release we might see some more triggers. Additionally you can develop your own triggers as well.

In the following code you can see usage of AdaptiveTrigger:

<VisualState x:Name="Normal"> <VisualState.Setters> <Setter Target="comboBox.Visibility" Value="Visible"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="700"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState> <VisualState x:Name="Mobile"> <VisualState.Setters> <Setter Target="comboBox.Visibility" Value="Collapsed"></Setter> </VisualState.Setters> <VisualState.StateTriggers> <AdaptiveTrigger MinWindowWidth="0"></AdaptiveTrigger> </VisualState.StateTriggers> </VisualState>

You can see that AdaptiveTrigger has only two parameters: MinWindowWidth and MinWindowHeight. These parameters allow to switch state of window based on size. In our example, if we have the width of the windows smaller than 700 pixels, we will collapse an element called comboBox.

In the next post I am going to show how to create your own trigger.

Written by Sergiy Baydachnyy

06/30/2015 at 10:40 PM

Raspberry Pi 2 and Windows 10: My first experience

leave a comment »

Finally, Microsoft published Windows 10 preview build for Raspberry Pi 2 (and not just for Raspberry). So, if you have Raspberry, you can visit https://dev.windows.com/en-US/iot and download the build and setup instructions.

Of course, it’s easy to prepare an SD card and put it to Raspberry but pay special attention that:

· You need to use microSD card class 10. I missed this requirement and was very upset when found that my Raspberry is not even trying to start. When I checked manual once again I checked my SD and found that it has class 4! So, I changed it and everything started working fine;

· First start requires much time to finish all things. So, you need to be patient;

· You need to connect your board to network using network cable. It’s a preview and many famous WiFi adapters don’t work on Raspberry right now. So, if your application connects to Internet you will need to use network cable all the time but if you want to create a simple LED project you need access to network at least for deploying your project;

If everything is ok you will see Raspberry image and important information like device name and IP address on the screen. So, your device is ready and it’s time to establish connection between your PC and Raspberry. In order to do it you can visit the following page to setup connection using PowerShell. I tried to make it several times and discovered some issues on my PC. Because I am not admin it was very hard to understand what happened there, so I want to share all stoppers I had:

· Set-Item issue – when I ran this command I got an exception with complicated message about private and public networks and some advice to change network from Public to Private. When I checked my network settings (Network and Sharing Center) I found that my network is Private but I have Virtual Ethernet Adapter which was created by Visual Studio installation. I simply disabled it and the exception was gone;

· Enter-PsSession – when I ran this command I got one more exception “The WinRM client cannot process the request. If the authentication scheme is different from Kerberos…” Once I got it I spent much time to understand how to setup WinRM but my knowledge in this area is not enough, so I selected the simplest way: I ran Gpedit.msc and navigated to Local Computer Policy->Computer Configuration->Administrative Templates->Windows Components->Windows Remote Management->WinRM Client. There I enabled Allow unencrypted traffic and Trusted Hosts and, additionally, I enabled all hosts there. And the problem was gone. I hope that you can find a way to configure it in a better way but I simply didn’t have much time to check all combinations because I wanted to start development!;

clip_image002

Once you connect to your Raspberry you can change password, device name, run some configuration cmdlets etc. Pay special attention that Raspberry supports two modes: headed and headless (with GUI and without GUI). You can read more about the modes here.

Right after you establish connection between your PC and Raspberry you can try to develop something. Thanks to Visual Studio it’s very easy to develop, deploy and debug solutions on Raspberry. Raspberry runs Remote Debuger by default so you should not make any additional configuration.

In order to start you need to select the language. You can select between Node.js, Python and standard languages for Universal applications like C#. Of course, I decided to use C# but you can easily install Python or Node.js tools from Connect site. So, in order to start you need to create a simple Universal application, change platform to ARM and select Remote Machine for deploying and debugging.

clip_image004

Finally I develop and deploy my first application for Raspberry:

clip_image006

Written by Sergiy Baydachnyy

05/04/2015 at 8:38 AM

Universal Applications: be ready for Windows 10 (part 2)

leave a comment »

In the previous post we started to discuss features and approaches to build Universal Applications. I am going to show that already today you may build applications which will be ready for Windows 10. And today we are going to discuss XAML.

Full Screen and Snap mode

When Microsoft introduced Windows 8, Windows Runtime and Modern UI patterns, there were three things which developers needed to know about applications: all Modern UI applications work in full screen mode; 1024×768 is minimal supported resolution for Windows 8 devices; for resolutions 1360×768 and more Windows 8 allows to show applications in Snap mode with fixed width in 320 pixels. Based on these assumptions many developers designed interfaces for their applications in 1024×768 resolution using these parameters like minimal amount of available space for application. In case of Snap mode, many developers ignored it and tried to avoid to design something for 320×768 resolution. Frankly speaking I didn’t like Snap mode as well. Usually I showed a message like this: “Application doesn’t work in Snap mode. Please, move the application to Full screen mode to continue”. This messages helped me to pass certification.

But everything is changing and Windows 8.1 added some more pixels to Snap mode. Today, default width of Snap mode for Windows 8.1 is 500 pixels. This amount is harder to ignore and that’s more important – Windows 10 allows to run Modern UI applications in window mode like legacy desktop applications.

image

So, if you are going to create the best UX in your application you should think about different resolutions in advance. Windows 8.1 already doesn’t support events which let the user see that application is in Snap mode, instead, Windows proposes the SizeChanged event. This event is related to Page and you can easy get access to page width and height in order to understand the current size and change layout according to it. The event handler can look like this:

void Page_SizeChanged(object sender, SizeChangedEventArgs e) 
{
if (e.NewSize.Width <= 500)
{
. . . .
}
else if (e.NewSize.Width < 1024)
{
. . . .
}
else
{
. . . .
}
}

So in order to guarantee the best UX in Windows 10 you should think about smaller resolutions. But there is a trick: if you already implement application’s layouts for small resolutions, can you apply it for Windows Phone application – I believe, so.

Therefore, in case of XAML and layouts you can think about resolutions only because both platforms support almost the same set of controls.

ViewState manager

Right now, we are ready to change layouts depending on width of the window. So, it’s time to think how to make it.

The best way to change layouts is using ViewStateManager there. You can use it in XAML to define different visual state groups. Each group can contain Storyboard with animations inside. You can use these animations to hide or show some controls, change ItemTemplate, change controls’ properties etc. It’s easy to declare several groups for different resolutions and, thanks to animations, specify different look for each layout.

<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="DefaultLayout">
. . . .
</VisualState>
<VisualState x:Name="Layout500">
. . . .
</VisualState>
<VisualState x:Name="Layout1024">
. . . .
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

As I mentioned before, you can change Visability properties, assign new ItemTemplate value etc.

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView" 
Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="itemListView"
Storyboard.TargetProperty="ItemTemplate">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{StaticResource smallItemTemplate}"/>
</ObjectAnimationUsingKeyFrames>

Onc, you defined all needed visual states, you can implement code, which allows to change visual state based on windows size. You can do it in SizeChanged event handler using this line of code:

VisualStateManager.GoToState(this, "Layout500", true);

I believe that we can finish for today but I am going to continue the series and next time we will discuss DPIs and images.

Written by Sergiy Baydachnyy

03/11/2015 at 6:16 AM

Universal Applications: be ready for Windows 10 (part 1)

leave a comment »

Several Days ago Microsoft made a first look at Windows 10 App platform. Of course, it’s great to have one developer platform and one core but we still have two months before Build. Therefore, many developers wonder, if they can do something right now to be ready for Windows 10. That’s why I decided to make a series of posts about Universal Applications to help developers start porting their applications right now. In order to do it I am going to describe several topics, which are most important for Universal application development for Windows 8.1 and Windows Phone 8.1. So, let’s start with templates and directives.

Universal Apps Template

Since Windows Phone 8.1 announcement developers got a chance to use Windows Runtime for both platforms. It allows to use the same application model, the same set of controls, the same async/await patterns etc. Of course, there was partial support for Windows Runtime since Windows Phone 8.0 but there was no chance to forget Silverlight and use Windows Runtime only. Windows Phone 8.1 brought Windows Runtime to the new level and developers may forget about Silverlight.

Therefore, developers got a chance to develop applications for both platforms with minimum amount of work. Of course, you still need to compile your application for Windows Phone and Windows separately and you need to upload two (or more) packages to the Store but, in many cases, you may use the same code and it relates not just to business logic but to interface as well.

In order to help developers get better experience there, Microsoft introduced Universal Apps template in Visual Studio (Visual Studio 2013 Update 3 and later), which helps to create applications for both platforms at the same time.

clip_image002

In fact, when you are creating applications using this template, Visual Studio is creating three projects: Windows Phone project, Windows 8 project and Shared project.

clip_image003

The idea is very simple. All things that you are adding to the Shared Project will be precompiled to Windows and Windows Phone projects. Therefore you can put there common resources, business logic and XAML pages, if you believe that they are common for both projects.

Many developers believe that it’s all that you need to know about existing Universal Apps template and that the best way to make universal applications is creating business logic in a Shared project and different pages for Windows Phone and Windows. But this is not true and this approach will not help you to be ready for Windows 10.

Directives

If you are going to make real Universal applications you need to know how to build universal pages and page logic as well. So, I will start with directives, which should help you to tune your code for different platforms.

Of course, Windows Phone and Windows 8 have some differences. For example, Windows Phone supports just buttons and menu items in applications bar but Windows can present any containers there; Windows Phone contains hardware or software emulated back button but Windows doesn’t and so on. So, from time to time you need to create code snippets just for Windows Phone or Windows. You can do it using #if…#endif directive. It’s possible thanks to WINDOWS_APP and WINDOWS_PHONE_APP constants. Of course you can define your own constants but I recommend to use these ones because it should be clear for many developers and Visual Studio Intellisense mode already supports possibility to switch between two platforms based on these constants.

clip_image004

So, if you are going to create platform specific code, you can use the following lines:

#if WINDOWS_PHONE_APP

//your code

#endif

Next time I am going to discuss common XAML pages for both platforms.

Written by Sergiy Baydachnyy

03/10/2015 at 2:37 AM