Sergiy Baydachnyy

Blog about technologies

Archive for September 2015

State triggers and Blend

leave a comment »

At last, Windows 10 is released and today developers have access to Visual Studio 2015 and Windows 10 SDK. I have already published some posts about Universal Windows Platform and Visual Studio 2015, and I promise lots of topics about it over next months; but today I want to drag your attention to Microsoft Blend 2015 tool which is included to Visual Studio installation.

Looks like Microsoft continues to invest in Blend and the latest release contains lots of new features. Today I want to talk about visual states editor new features.

In order to see the new features just create a new project in Blend and select MainPage.xaml in Solution Explorer. Once you do this, Objects and Timeline window will show structure of the page. Usually, when we create visual states we work with main container such as Grid. So, in order to create several visual states it’s better to select the root Grid element in Object and Timeline and States windows to start editing visual states.

Blend allows you to edit visual states without coding at all. With the help of the States window you can create as many states as needed, and once you select a state, Blend switches editor to Record mode (Ctrl+R). In this mode you can change properties of any user controls and all these changes will be included to the selected state automatically. So, I propose to create just one state using Add State button in States window and select the main grid to change some properties. For example, you can change Opacity and Visibility using Properties window.

clip_image002

If you open XAML document you can find the following code there:

<VisualState x:Name="Normal"> <VisualState.Setters> <Setter Target="grid.(UIElement.Opacity)" Value="0.5"/> <Setter Target="grid.(UIElement.Visibility)" Value="Collapsed"/> </VisualState.Setters> </VisualState>

So, you can see that Blend editor is fully integrated with the new approach that Universal Windows Platform implements thanks to Setter elements.

If you want to use the old approach or animate your properties from one state to another, you can continue to use the timeline and Blend will use animation instead of setters.

One more feature of Universal Windows Platform is state triggers, which allow you to move interface from one state to another without coding at all. UWP supports just AdaptiveTrigger but you can create your own triggers. Let’s see, how to use triggers in Blend.

I propose to add a class to the project which will have just one property but this class should be inherited from StateTriggerBase:

class MyTrigger: StateTriggerBase { public int State { get; set; } }

Of course, this class doesn’t have any sense because it does not have any logic inside but it’s enough to show it in Blend. Just recompile the application because Blend will look at assemblies.

Let’s try to apply the created trigger to one of the states using the States window. Pay attention that this window contains new button called edit adaptive triggers:

clip_image003

Just click the button for any state and Blend will show a dialog, which allows to select available triggers for the project:

clip_image005

Just select our trigger and Blend will allow you to initialize all public properties there (we have just one):

clip_image007

Enter any value there and click OK. Blend will generate the following code:

<VisualState.StateTriggers> <Code:MyTrigger State="10"/> </VisualState.StateTriggers>

Therefore, if you want to create a real adaptive interface and need to create lots of states and use many triggers, Microsoft Blend is the best tool for that.

Advertisements

Written by Sergiy Baydachnyy

09/07/2015 at 9:20 PM

UWP: New features of Launcher class

leave a comment »

In this post I want to discuss how to establish communications between Universal Windows Platform applications. It was a problem since Windows 8 because each application is running in its own sandbox without access to data of other applications. Of course, Windows 8.x supports several ways to invoke external applications and pass data to them. For example you could use share charm or use Launcher class. But all these methods have some disadvantages. Let’s look at Launcher class.

In Windows 8.x Launcher class allows to launch external applications based on Uri. The most common protocol for Uri is http and you can use it to launch browser but applications can register their own protocols for own needs. For example, in Windows 10 to invoke Settings window you can use ms-settings protocol and create Uri for Launcher class based on it:

await Launcher.LaunchUriAsync(new Uri("ms-settings:"));

You can see that in order to launch external application you should call LaunchUriAsync method which doesn’t allow to pass anything except Uri. If you need to pass some parameters to external application, you could use the same approach as for http protocol: get parameters in Uri. But if you need to pass file as a parameter you cannot make it using LaunchUriAsync. Frankly speaking, Launcher class supports LaunchFileAsync method but that method supports StorageFile as a parameter. So, you can not pass several files and you can not combine both methods (launch application using Uri and pass file at the same time). Even in order to pass file to a(??) third-party application it is required to register extensions of accepted files. Additionally, LaunchUriAsync and LaunchFileAsync don’t allow to control which application should be launched. If several applications register the same extension, user needs to select an application from the list. Finally, there was no way to understand if an application is launched and how to get some result back.

Let’s summarize all disadvantages, which Launcher class has in Windows 8.x:

· Allows to pass Uri or file using two different methods without a way to combine them;

· Doesn’t allow to pass several files;

· System might ask user to select an application from the list;

· There is no way to know if an external application is launched;

· There is no way to get response from an external application;

But in Universal Windows Platform, Microsoft made huge investment to Launcher class and today developers can avoid all mentioned disadvantages. Let’s see which changes were implemented there.

Look at the following code:

LauncherOptions options = new LauncherOptions() { TargetApplicationPackageFamilyName = "Microsoft.MicrosoftEdge_8wekyb3d8bbwe" }; await Launcher.LaunchUriAsync(new Uri("http://www.microsoft.com"), options);

When running this code we asked Launcher to launch an application which has defined application package name. This approach is very useful for corporate systems when you developed for customers more than one application. Using LauncherOptions you can guarantee that system will run exactly the application you need from your bunch of applications. Of course, you need to know the application family name but you can easily to find it using the Store:

clip_image002

Additionally, you can use FindUriSchemeHandlersAsync method of Launcher class to get information about all packages which accept the selected schema:

var res = await Launcher.FindUriSchemeHandlersAsync("http");

This method returns an array which contains all needed information including package name:

clip_image003

Of course, if package doesn’t exist in the system, LaunchUriAsync method will return false and you can ask users to install an additional application.

Launcher class contains one more method, QueryUriSupportAsync, which allows to get information if selected Uri is supported in the system:

var res = await Launcher.QueryUriSupportAsync(new Uri("http://www.microsoft.com"), LaunchQuerySupportType.Uri);

This method doesn’t return any information about external applications but allows to check if you can run an application using a passed Uri. And what is more important, this method allows to check result using package family name and even to understand if external application can return a response.

I would like to note that you can use the same bunch of methods for open files using external applications: LaunchFileAsync, FindFileHandlersAsync, QueryFileSupportAsync. Of course, these methods don’t resolve the problem with multiply files but UWP brings an opportunity to use LaunchUriAsync method for passing several files (references) as parameters. Let’s see how to implement it.

The idea is in using of SharedStorageAccessManager class. Thanks to this class you can share files between applications using tokens.

var token=SharedStorageAccessManager.AddFile(myfile);

Because token is a string, you can use it as a parameter in Uri. So, you should not pass any IStorageFile objects or anything special – just the same Uri. And it is possible to create as many tokens as needed.

External application can redeem tokens and get access to IStorageFile objects:

string myFileToken = queryStrings.GetFirstValueByName("GpxFile"); if (!string.IsNullOrEmpty(myFileToken)) { StorageFile file=await SharedStorageAccessManager.RedeemTokenForFileAsync(myFileToken)); }

Once the token is redeemed nobody can redeem the token once again. But the token may live for 14 days. So, if the application discovers a problem with launching of an external application, there is a way to delete token from the list using RemoveFile method.

Of course, in case of file token it’s easy to include tokens to Uri but you can pass any serializable objects what you want. In order to do it you can use ValueSet class , which is a dictionary of serializable objects. Developers can use it to pass tokens as well but it’s possible to pass anything:

ValueSet v = new ValueSet(); v.Add("token1", token); var f = await Launcher.LaunchUriAsync(myUri, options, v);

Finally, Launcher class allows to launch Uri for results. Imagine an application for making a payment. You can use this application as external method to make payments inside your own application but you need to get information from external one if payment is processed and, probably, some information to check if payment is received. In Windows 10 you can implement it using LaunchUriForResultsAsync method. This method has the same parameter list like LaunchUriAsync but it returns LaunchUriResult object instead of bool and you can use this object to see status and get results if launch was succeeded.

var result = await Windows.System.Launcher.LaunchUriForResultsAsync(myUri, options, inputData); if (result.Status == LaunchUriStatus.Success) { ValueSet theValues = result.Result; //do something here }

Therefore, all Windows 8.x problems with Launcher class are gone and today you have a great way to make communications between different applications.

Written by Sergiy Baydachnyy

09/03/2015 at 9:22 PM

UWP: Clipboard

leave a comment »

Starting with Windows 10 you can implement clipboard operations not just for desktop but also for all Windows 10 devices.

I already published the post about Drag and Drop functionality where we used DataPackage class in order to prepare data for sending to external applications and DataPackageView class to get data which was dragged from external source. In case of Clipboard we need to use the same approach but instead of event handlers we should implement content menus with standard commands there.

Let’s see how to implement Paste functionality. I am going to use the same application which I used in Drag and Drop post because we can use the same code. I am going to allow Paste feature for images, so I will show images in ListView and I need to implement a simple MenuFlyout:

<ListView Margin="50" Name="listView" RightTapped="listView_RightTapped" IsRightTapEnabled="True"> <ListView.Resources> <MenuFlyout x:Name="menuFlyout"> <MenuFlyout.Items> <MenuFlyoutItem Name="pasteItem" Text="Paste" Click="MenuFlyoutItem_Click"></MenuFlyoutItem> </MenuFlyout.Items> </MenuFlyout> </ListView.Resources> <ListView.ItemTemplate> <DataTemplate> <Grid> <Image Source="{Binding Source}" Width="200" Margin="10"></Image> </Grid> </DataTemplate> </ListView.ItemTemplate> </ListView>

You can see that I declared MenuFlyout like a resource of ListView. MenuFlyout class doesn’t allow to show menu automatically. So, I allowed right click for my ListView and implemented RightTapped event handler in the following way:

private async void listView_RightTapped(object sender, RightTappedRoutedEventArgs e) { var format = Clipboard.GetContent().Contains("FileDrop"); pasteItem.IsEnabled = format; menuFlyout.ShowAt(listView, e.GetPosition(null)); }

In order to implement a better UX I check if any files are available and enable or disable menu item.

Finally, if user selects Paste menu item I use Clipboard class in order to get all available files and prepare them to show in ListView:

private async void MenuFlyoutItem_Click(object sender, RoutedEventArgs e) { var files = await Clipboard.GetContent().GetStorageItemsAsync(); List<BitmapItem> items = new List<BitmapItem>(); foreach (StorageFile file in files) { try { BitmapImage bi = new BitmapImage(); bi.SetSource(await file.OpenAsync(FileAccessMode.Read)); items.Add(new BitmapItem() { Source = bi }); } catch { } } listView.ItemsSource = items; }

You can see that we used the same code like in the Drag and Drop post. We changed just the first line of code – we used Clipboard class to get DataPackageView.

Therefore you can see that Drag and Drop and clipboard features are better to implement together because you can use the same approach and these features are now universal.

Written by Sergiy Baydachnyy

09/03/2015 at 9:16 PM