Microsoft Build 2017 Highlights

Needless to say, #MSBuild is the most wanted conference for Microsoft developers. Build 2017 took place in Seattle. I was lucky to take part in the event as an attendee. The event was interesting not only because of announcements. It’s a chance to discuss technical topics with other engineers and get answers on questions directly from Microsoft specialists.

During these days Microsoft announced their focus and shared roadmaps of different projects. From the very beginning, Satya Nadella outlined a new strategy of the company. From mobile-first and cloud-first, Microsoft is moving towards an intelligent edge, inside of which is an intelligent cloud. The company focus is shifting from devices towards where and how people interact with all gadgets they own. Microsoft erases boundaries between platforms and wants to connect people activities together with help of AI and serverless technologies.

 

Microsoft Intelligent Cloud

Microsoft builds intelligent cloud around its Azure services. New cloud services and serverless computing were presented at the first-day keynote:

  • Microsoft Cosmo DB;
  • Azure databases for MySQL and PostgreSQL;
  • Azure Functions Runtime.

Azure Cosmo DB is distributed, a multi-model database with extensible APIs, easy scale, fast response and high availability.

Azure Functions Runtime is serverless application development tool. You install the runtime at your environment, deploy and launch your serverless functions there. As soon as it’s decided, you can seamlessly move the functions into the cloud. It means you don’t need to manage Microsoft Azure account if would like to try serverless computing. The minimum requirements is a machine with Windows Server 2016 or Windows 10 Creators Update with access to a SQL Server instance.

It’s worth to mention about improvements related to Azure Services management. Scott Hanselman demonstrated new possibilities of Azure Cloud Shell. Azure CLI gives you full control and flexibility. You can create 1000 instances of virtual machines on a fly with only one command. There are apps for iOS and Android to help you to manage and monitor your web-services from anywhere. Azure Cloud Shell is available in the apps also.

 

Microsoft Intelligent Edge

Since the last two years, Microsoft made a significant progress in artificial intelligence. The company is strong in computer vision, speech and search. They made available these technologies for other developers with Microsoft Artificial Intelligence APIs.

Microsoft intelligent edge or in other words AI platform is presented by cognitive services, bot framework, deep learning and data analytics tools. Cognitive services APIs documentation and code examples are available for the most popular programming languages. The company pays a big attention to customization. With help of new Custom Search, Custom Decision, and Custom Vision services, it’s easy and fast to train your model with any data, and with few clicks, you can utilize the mode through an endpoint.

Conversational AI SDK is the completely open source:

github.com/microsoft/botbuilder

github.com/microsoft/botframework-emulator

stackoverflow.com/questions/tagged/botframework

azure.microsoft.com/services/bot-service

The new features of the bot framework include:

  1. Channels for Cortana, Bing and Skype;
  2. Adaptive cards;
  3. Bot payments and analytics;
  4. And more.

Adaptive cards is an open source framework. It allows to build a UI widget with a JSON and show it in a communication channel.

If you are curious about Microsoft progress in other AI services, you can try out and experiment with them at Cognitive Services labs portal at very early stage.

There are many good examples how Microsoft helps business move forward with AI. I want to highlight a success story of UBER. It uses Microsoft Face API to identify drivers. Video broadcasting at the conference was powered by Microsoft speech recognition services.

 

Windows 10 Fall Creators Update

The second day was full of news about Windows, cross-device and cross-platform development. The next significant Windows 10 update is coming in Fall 2017, it’s named Microsoft Fall Creators Update. The new version of Windows includes fluent design, timeline feature, files on-demand, cloud clipboard and new Story Remix application.

Timeline feature gives users cross-device experience. A user can work with an app at his Windows PC, afterward he switches to iPhone and with help of Cortana, continues his interactions within the mobile app from the spot he left it at Windows. It works in both directions. Moreover, If the app is not on his iPhone, Cortana asks to install it from Apple Store. This amazing functionality is powered by Microsoft Graph and Project Rome. At Build, Microsoft announced Project Rome SDK for iOS.

OneDrive files on-demand gives you the possibility to access all your cloud files and folders from File Explorer without downloading them.

Copy from Windows and paste to an iPhone becomes available through Microsoft Swiftkey clipboard.

The new Creators Update also brings iTunes and Ubuntu at Windows 10. Users will be able to install this software directly from the Microsoft Store. Apart of that, Spotify for Windows 10 was promised.

 

New standards in cross-platform development

Microsoft does big efforts to make Windows home for all developers. They want developers for any platform to have a comprehensive set of tools to build apps. With that said, many announcements were related to cross-platform development.

First of all, they introduced XAML Standard 1.0 and .Net Standard 2.0.

XAML Standard aligns markup syntax, used at Xamarin.Forms and Windows 10. The main idea is to make it possible to re-use Windows 10 pages in Xamarin applications. Once, a TextBlock is defined in Windows 10 page markup, it will behave in the same way at Xamarin.Forms. Feel free to extend the standard specification with your proposal.

Development experience with.Net Core can be painful when you are not able to reference a NuGet package in your project. The current situation is that many NuGet packages are still not available for .Net Core applications, so the development is slow down. Worse, when this fact makes .Net Core as a not desirable technology. Microsoft is aware of this problem and wants to make it’s simpler to build a library, which works on any version of the existing frameworks: .Net Framework. Xamarin & Mono, .Net Core and UWP. The new version of .Net Standard 2.0 extends cross-platform APIs and covers the top 70% of NuGet packages.

 

Continuous delivery for mobile apps

Solid design and high quality are important factors for successful apps. The diversity of devices increases testing complexity and delays product releases. Health monitoring and analytics keeps an app quality in shape and gives a feedback about the app features usage. Visual Studio Mobile Center is a comprehensive solution for mobile apps testing and monitoring. It contains well known HockeyApp and Xamarin Test Cloud. Eventually, automated build and a full range of Windows devices come to the Mobile Center this fall.

 

Cross-platform development with Xamarin

The last announcements I want to highlight in the article are my favorites. It’s about cross-platform development with Xamarin.

Xamarin Live Player is an amazing tool. It extremely simplifies development apps using Xamarin and C#. You can change a piece of code when debugging and the changes are immediately applied. Works in the same way as live-reload in Chrome. With the Live Player, you don’t need a Mac anymore to run and test your app on iPhone. It works like a charm, just plug in an iPhone to Windows PC, choose the Live Player option in Visual Studio and that’s it. The tool is available as a preview for Windows and Mac.

Xamarin team presented a new project, the codename is Embeddinator 4000. It is a future of cross-platform development. In two words, you pack .Net code with Embeddinator into a library and utilize the library in a native iOS, Android, Mac or Linux app.

 

Fun

Apart from technical talks, there was a fun part. I traveled with my team mate. It was amazing to test the app we are currently working on at Microsoft devices with a different scale. We checked how the app works on Microsoft Surface Hub and Microsoft Surface Studio. I also tried Stryker software, tailored for a HoloLens device to help people to design operating rooms.

 

 

In general, I enjoyed the conference format, content and the way it was organized. Definitely, I will attend it the next year :).

UWP: Drop down selector

Intro

Drop down selector can be used in scenarios when a user has to choose an option from a short list of values, but it doesn’t make any sense to show the whole list of values at a page. Can be useful to choose a sorting order or a filter:

There is no a similar control in UWP SDK. How to build a custom one? My intent in this article is to demonstrate how to do it with few lines of code, using based UI elements.

Base properties

Let’s name the new control DropDownButton and inherit it from Windows.UI.Xaml.Controls.Control. As usual, in the default constructor, it’s required to define DefaultStyleKey, in order to apply a style defined in Generics.xaml file:

DropDownButton needs at least ItemsSource, ItemTemplate and SelectedItem. These properties allow to bind data, apply custom view for a data item and use a selected value. And of course, they supposed to be dependency properties:

XAML template

The control template has the following parts:

  • To show a selected item, I use TextBlock;
  • ListView is to allow to choose a value;
  • And FontIcon, to highlight that the control is a kind of a selector.

The List part needs to be hosted in a popup, because we want to show it, when the user taps on the button. I use Flyout, not a popup. I define it as attached to the root Grid of the template:

There are two visual states defined in the template, PointerDown and PointerUp. They used to show when a user taps the control. I manage the animation with overridden OnPointerPressed and OnPointerReleased methods:

Codebehind

The core logic of the control is to show the list with available options, select an option, show the selected value an close the list on user tap outside of the control boundaries.

The easiest part is to open the list with items. To achieve that, I subscribe on Tapped event and call FlyoutBase.ShowAttachedFlyout in the event handler:

Another substantial part of any custom control is OnApplyTemplate method. This method is the entry point to subscribe for events of the elements, defined in the control template. It’s very important to have this method written correctly:

I want to update the button icon, when the flyout has been opened or closed. DownUnicode and UpUnicode are constants, which keep arrow down and up glyphes :

When a user selects an item, the list of the option should be hidden and selected value is shown. Selection changed event handler is also very simple:

Now the control is ready to use in your application:

The sources are here, fruitful coding!

Good to know recipes about WebView

WebView is a powerful UI component. It was extended in UWP with new features, which give developers more control on content rendering. I would like to highlight some of them, which I found useful.

Execution mode.

When your app is launched at desktop, WebView loads and renders html content in the UI thread. When it’s a mobile device, then html content is processed in a separated thread. If you want to override this behavior and host WebView in a non UI thread at desktop, then you need to set WebView.DefaultExecutionMode to SeparateThread value. WebView.DefaultExecutionMode is a static getter. And the only one way to set a value for that is to pass it into a constructor. So, no way to declare DefaultExecutionMode in XAML. You need to create WebView in code behind and add it to the root panel:

Navigate with custom headers.

WebView.NavigateWithHttpRequestMessage method allows to send a request with a custom http message. This object provides the access to a request headers and content:

Only GET and POST requests can be send with WebView.NavigateWithHttpRequestMessage.

Catch and modify a request.

Every time WebView starts to load html document, it raises NavigationStarting event. At this point, it’s possible to cancel the navigation by setting Cancel property of the event arguments to true. You can use this event to catch an http GET request, add your custom headers or parameters and send it again:

In the handler you can’t access a request body, so it can be applied only for a GET. There is no way to modify POST or DELETE requests.

Handle a deep link.

UI in your app can mix html content with native pages. And navigation between html pages and native content can be done with help of mobile deep linking. In order to provide smooth experience for users, you have to handle deep links gracefully. WebView fires UnsupportedUriSchemeIdentified event, when it can’t process an URI scheme. Just subscribe for the event and process a navigation URI manually.

Rotate a picture.

Windows Photos application allows a user to rotate an image and save a copy to a local storage. How would you implement the same functionality in your app?

There are two approaches:

  1. We can get a raw pixel data of a picture and then rotate the array of bytes;
  2. Universal Windows Platform has API, which helps to solve this task.

Let’s take a look at both of them.

Access a raw pixel data.

To access a pixel data we have to utilize a chain of objects. First of all, we need to decode an input image data with an instance of BitmapDecoder. From BitmapDecoder, we can get an instance of PixelDataProvider. And then, use PixelDataProvider.DetachPixelData to get an array of pixel data.

The code bellow demonstrates how to do it:

Rotate a pixel data clockwise.

A picture rotation implies rotation of a two-dimensional matrix. Such kind of a transformation means that columns of an input array are converted to rows of an output array and rows of the input becomes columns of the output. Taking that in account, we can express the logic of a matrix transformation in the following code:

I set variable output to a two-dimensional array of int and used number of columns as number of rows for the output. I’m using a row index of the output array to access columns of the input array. And index of an input row can be calculated from an output column index.

When dealing with a picture, we have a one-dimensional array of a pixel data and a pixel length typically is 4 bytes. The algorithm to rotate a one-dimensional array has 3 steps:

  1. Calculate row and column indexes of a two-dimensional matrix from an index of an input array;
  2. Calculate rotated row and column indexes;
  3. Use the values calculated at the step 2 and convert them to one-dimensional index.

I wrapped it up in RotateClockwise method:

The method takes pixel data and size of a picture. When rotated row and column indexes are calculated, I’m traversing a nested loop to copy values from an input pixel to a rotated pixel. By rotated pixel, I mean a pixel from the rotated matrix.

Save an image.

Now, we can save transformed matrix to a local storage. BitmapEncoder can help us with that. I call a staic method BitmapEncoder.CreateForTranscodingAsync to create an instance of encoderAnd afterwards I use BitmapEncoder.SetPixelData and BitmapEncoder.FlushAsync to apply a pixel data and save the result.

The height of the original image should be used as a value for width parameter and the width for height parameter when calling SetPixelData

Rotate using BitmapTransform.

The described approach of a rotation gives us basic understanding of simple transformations that can be applied on a bitmap. But in a real project we don’t need to manipulate with pixels. BitmapTransform class has a set of properties, which can modify a picture depending on our needs. I updated SaveRotateAsync to use BitmapTransform to achieve the desired result:

We can not only rotate, but flip and scale with the help of an instance of BitmapTransform class.

Wish you fruitful coding!

Horizontal swiping in ListViewBase control with mandatory, centered snap points.

You might need to implement a swiping behavior in a list similar to FlipView control. In FlipView, a swiping always ends at the center of an element. Unlike it works by default in ListViewBase control, where user can see many items at once and stopping points are randomly chosen. But FlipView is not really wanted, when it’s required to display left and right items. The behavior I needed to achieve:

Swiping behavior

 

Snap points type and alignment.

The easiest way to customize user interactions with a list is to configure ScrollViewer control. ScrollViewer has two properties, which allow to control horizontal swiping. It’s ScrollViewer.HorizontalSnapPointsType and ScrollViewer.HorizontalSnapPointsAlignment. MandatorySingle snap points type with Center alignment makes ScrollViewer always stop at the center of a list element.

 

Customizing horizontal swiping in GridView.

HorizontalSnapPointsType and HorizontalSnapPointsAlignment are not attached properties. They can’t be easily accessed from GridView.

Template of GridView is the best place to set MandatorySingle and Center values for internal ScrollViewer:


I also override ItemsPanel in this XAML, because I want to show items in a horizontal panel.

 

Example.

Take a look at the example here. Launch the app at Windows mobile emulator and hit Snap points example button. As soon as the next page is being loaded and a list with images is being shown, swipe to the second item and immediately to the first one. You will notice a bug. The first item becomes unreachable. I fixed the issue with inserting empty items in the beginning and the end of the list:

GridView.ScrollIntoView() allows to make the first not empty item logically focused:

To make the example works fine, go to HorizontalSnapPointsPage.xaml.cs and undo commented InsertEmptyItems() and ScrollToFirstItem() methods. Swiping in the list works as expected now.

Wish you fruitful coding!

One more time about localization.

To localize a UWP app, a developer needs to do a few things:

  • create Resources folder in the solution;
  • add a subfolder with the name of the app default locale, for example en-US;
  • set default locale in AppManifest;
  • add Resources.resw to the created subfolder;
  • utilize x:Uid directive in XAML to apply a resource value.

After the main functionality is ready, the same steps can be applied for locales you want to support in the app. You also might need to create a service to load and access the resources. But intent of this article is to take a deeper look at the internal structure of localized resources in a package, when an app is ready to be published to the store.

With Universal Windows Platform, a new way of an app distribution was introduced. Microsoft suggests to create a bundle when your app is ready for submission to the store. Appxbundle is an archive file, which contains app packages for: x86, x64 and ARM. What is also interesting about app bundle is that allows to manage resources included into a package. Usually, an app has string resources or images with different resolutions for different locales. And for sure, when a user installs an app, he doesn’t need everything at his device. That’s exactly what app bundle helps to solve. All resources in an app bundle are packed in some way and when a user downloads an app, he gets localized resources, related to his device language settings. Thus, users from USA won’t get German resources, because they don’t need them.

This image can give you some insights about internal structure of a bundle:

Apart of the files related to the locales, there is also AppManifest file which contains metadata about the resources.

When a user installs a package distributed as not a bundle, he gets all localized resources used in the app. And that’s the main difference between a bundle distribution and the distribution used for Windows 8.1 apps.

If localized resources are downloaded respectively with a device language settings, how then programmatically apply different locales for UI? What if users want to set a different language? A language which is not the same as in device settings? That’s a tricky part of appxbundle. Even, you might not notice any issue with that when developing your app. But when try to change a language when the app is installed from a bundle, you will see that not every locale is applied properly. That’s because end device doesn’t have all files with localized resources.

The described issue can be handled in different ways. One possible solution is implemented in Bing News app. When the user chooses the app language, it asks to add chosen language to the device settings and set it as display language. Afterwards, an update will be installed by Windows. I suspect that Windows also will update the app with required resources file from the store.

The second solution is to implement custom localization and apply a resource value with bindings instead of x:Uid directive.

The third solution is to publish your app in the old way, with a package per configuration. As I mentioned before, if create a package but not a bundle, all localized resource will be included to that package. Thus, this approach gives more flexibility while can significantly increase the size of downloaded package for final users.

Once you started to distribute an app as a bundle, it won’t be possible to switch to a package per configuration. Dev center forbids an update with separated packages above appxbundle.

Actually, that’s not always forbidden. Our team had a bad experience with that. We published an update as a bundle for existing Windows 8.1 app. In other words, new Windows 10 app as an update for Windows 8.1 app. Afterwards, we figured out that localization doesn’t work as we expected. We decided to switch to a package per configuration distribution. We did that update and when submitting, it was allowed to upload three separated packages. As soon as the update became available, the users started complain about a crash when the app was launching.

That was really painful. It took significant amount of time to figured out the reason. When an update is being installed, all localized resources are being merged. Thus, the system tried to merge the resources from the installed bundle with the resources included to a new package. Such merge is not possible. And it wasn’t easy to catch the reason.

The main lesson – don’t switch from a bundle to the old way of distribution. It’s very possible that you will get some issues with that. But migrating to a bundle from the old way of distribution works well.

Fruitful coding!

URL builder

To get data from a REST service does not require a lot of work. A developer needs to create a query and pass the query string to an instance of HttpClient.

Fair enough. But lack of the logic, which manages how URLs are built, eventually will lead to code spaghetti with zillions of String.Format expressions and duplications.

Even more, at some point you might need to switch an app to a test environment. It means, that your code should create a query taking in account some app settings.

To get rid of the outlined complexity can help Builder pattern.

Any url to a REST api service has similar structure:

https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=twitterapi&count=2

or

scheme://host/api version/relative path?query parameters

If we would like to build a client for Twitter, we would use scheme+host+version in every query. That’s a common part. URL builder is responsible to compose the common part with relative path and adds parameters to the resulting string.

Using Builder pattern, implies initializing an object without parameters or with few of them. The construction of the object is done during runtime. In my case, UrlBuilder has a constructor, which accepts a host string and a version.

Relative path and parameters can be added later depending on the context:

An example of usage:

It’s useful to wrap up an UrlBuilder initialization. A factory is a good way to do it. Let’s back to an example for Twitter API.

We can have a parent class to keep base logic:

And another factory for statuses services:

The example contains two methods. But of course, the factory can be extended depending on your needs. Personally, I create a factory per services group. For Twitter API, I would add a factory for statuses, friendships and etc.

That’s it about UrlBuilder.

Fruitful coding!

UWP: Back navigation

In Windows Universal app, when user has been navigated back, the top page at the navigation stack is being re-created again. That’s because a page itself is not kept in memory, when the user navigates forward to another page.

Let’s imagine an app. The first page of the app has a list. The user can scroll the list down and when he taps a list item, he has been redirected to the item details page. When the user presses back button, the main page is appeared. But the state of the page is not preserved. The user sees the same list with initial scroll viewer position. He has to scroll again to the item he left the page.

How to improve the described scenario to make the user happy? In our example, a developer has two options:

  1. Maintain ViewModel of the main page as Singleton and keep ScrollViewer vertical offset in the ViewModel;
  2. Enable UI cache for the main page.

I prefer the second one.

Navigation cache mode.

Page.NavigationCacheMode is the property, which allows a page to be stored in memory if the value of the property is set to Enabled or Required. In our case, the MainPage with enabled NavigationCacheMode, will be created once. Furthermore, the details page, with enabled navigation cache, is also created once and will be reused to show details of every data item. Thus, a page with NavigationCacheMode=Enabled stays in memory even the user navigates back or forward from the page.

Loaded EventTriggerBehavior and back navigation.

XamlBehaviors is a great library. It allows to get rid of event handlers in a page class and bind event handlers with commands exposed by ViewModel at XAML level. But be aware about using EventTriggerBehavior for Loaded event together with enabled NavigationCacheMode.

Let’s assume we have MainPage in our app with navigation cache is enabled:

 

In page XAML, there is EventTriggerBehavior which executes a command when the root element has been loaded. And a button, which navigates the user to another page, when it’s been clicked:

When the page is being loaded in the first time, LoadedCommand executes as expected. But what happens, when the user goes back from another page to the MainPage? If the user navigates back, Loaded event for the root Grid fires and I expect LoadedCommand to be executed as well. As you can guess, it doesn’t work in this way. When the user navigates back, EventTriggerBehavior is attached to the root element after the element has been loaded. So, for the described case, LoadedCommand never will be triggered.

For similar scenarios, it’s better to subscribe for FrameworkElement.Loaded manually and execute a command in code behind. Either, override Page.OnNavigatedTo and call your logic from there.

Fruitful coding!

UWP: BindingExpression errors in ListView with a heterogeneous collection

Recently, I got BindingExpression exceptions when was creating some UI with ListView:

Error: BindingExpression path error: ‘Weight’ property not found on ‘HeterogeneousListView.Data.Milk, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Weight’ DataItem=’HeterogeneousListView.Data.Milk, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

Error: BindingExpression path error: ‘Liters’ property not found on ‘HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Liters’ DataItem=’HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

Error: BindingExpression path error: ‘Weight’ property not found on ‘HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Weight’ DataItem=’HeterogeneousListView.Data.Cookie, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)

You might seen similar errors when trying to bind a data item to a wrong template. The difference in my case is that the UI looked well, without any visible issues. I prepared a test project to reproduce the bug. The code is at github.

The test application shows some heterogeneous data in a ListView. My test data is three objects: Cookie, Milk and Orange.

There are two lists in the app. The lists have various approaches of applying a DataTemplate for an ItemContainer. For the left ListView, I set the ListView.ItemContainerSelector property to an instance of my custom DataTemlateSelector:

As you noticed, I override DataTemplateSelector.SelectTemplateCore
to choose a template for a data item. If you scroll down the left list, you immediately will see the errors in Debug Output window of VisualStudio. The fact, that the errors are appearing when scrolling the list, made me think that the realization of items works wrong. And most probably the bug in ProductTemplateSelector. If uncomment the debug lines in ProductTemplateSelector.SelectTemplateCore method, the output will show something interesting:


Container for: Orange 3

Data Cookie 98

Error: BindingExpression path error: ‘Pieces’ property not found on ‘HeterogeneousListView.Data.Orange, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’. BindingExpression: Path=’Pieces’ DataItem=’HeterogeneousListView.Data.Orange, HeterogeneousListView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null’; target element is ‘Windows.UI.Xaml.Controls.TextBlock’ (Name=’null’); target property is ‘Text’ (type ‘String’)


Container for: Orange 4

Data Orange 99


Container for: Cookie 98

Data Cookie 98


Container for: Orange 99

Data Orange 99

It says that an ItemContainer is being reused for a data item and DataTemplate.SelectTemplateCore is being executed twice for the same data item.

In fact, DataTemplateSelector has two versions of SelectTemplateCore:

And which version a developer needs to utilize depends on underlying ItemsPanel. If you use GridView or ListView with ItemsStackPanel or with ItemsWrapGrid then SelectTemplateCore(Object) needs to be overriden. By default, the underlaying panel for ListView and GridView is ItemsStackPanel. But if ItemsPanel is VirtualizingStackPanel or WrapGrid then SelectTemplateCore(Object, DependencyObject) should be implemented. The rule applies to any ItemsControl.

I override the wrong version of SelectTemplateCore in my ProductTemplateSelector. That’s the origin of the error. Uncomment ProductTemplateSelector.SelectTemplateCore(Object) in the example, run the app. The list now works smoothly.

What I also want to show you is how to apply a DataTemplate for an ItemContainer without using ListView.ItemContainerSelector. Starting from Windows 10, ListView and GridView controls have a new  ListViewBase.ChoosingItemContainer event.

In the test app, the ListView with custom implementation of ChoosingItemContainer is shown at the right part of the MainPage. And the handler for the event is very simple:

 

Needless to say, that ChoosingItemContainer gives better control when creating an item container. DataTemplateSelector is very simple to use and it does what it does. But when it requires to gain some performance benefits, then the best way is to implement a handler for ChoosingItemContainer event. You can also get more ideas about the usage of the new event from MSDN.

Fruitful coding!

UWP: range selector control

Slider control lets the user to select a value from a range. What about selecting multiple values from a given minimum and maximum?

There is no possibility to tune Slider to work as it depicted above. That’s a case to implement a custom control. Before we start, download an example from here.

Main properties.

The new control is going to have minimum and maximum properties to restrict user input, start and end range to save what the user has selected. Let’s begin from introducing a new class RangeSelector with the required dependency properties:

Style and template.

When RangeSelector is added and inherited from Windows.UI.Xaml.Controls.Control, we can declare the style and template for the control. Any custom control style should be placed in Themes/Generic.xaml file:

Don’t forget to update constructor to apply the defined style when RangeSelector is being created:

The visual part of any control is a template. Slider control templae has two rectangles whith a thumb. A Slider thumb is Border element. The full template easy to get with Blend. A good article about how to do it is here.

My RangeSelector has two thumbs, left and right. I utilize two rectangles to apply selection effect. The first one, I use to visualize a set of available values. And another rectangle, to show a selected range. When the control is loaded, the first rectangle is not visible because the full range is selected. In the template, the both rectangles are placed at the same level of logical tree:

I use clipping to shrink or expand the track. The thumbs have RenderTransform set to TranslateTransform. My intent is to use TranslateTransform.X property to update a thumb position, when the user is dragging a thumb:

Finally, the completed style:

Control.Foreground property is used to highlight a selected range and Control.Background to show space available for dragging.

Handle user input.

Now, lets subscribe on DragStarted and DragCompleted events. The right place to do that is RangeSelector.OnApplyTemplate() method. Inside the method we can get references to the elements we defined in the style and add required events handlers:

LeftThumbDragDelta and RightThumbDragDelta are responsible for updating the horizontal position of the thumbs. There are two corner cases that we need to take care of:

  1. The thumbs can’t intersect;
  2. The thumbs should be steak to bounds of the track rectangle.

To prevent the intersection from the left side, I check if sum of the left thumb position and a horizontal delta is less than the right thumb X coordinate. For the right thumb, I only apply a shift if the right thumb X positioin is greater than the left thumb X position. To keep the both thumbs on the track, it’s enough to compare the sum of the current positoin and a horizontal change with the point (0,0). Less words, more action. The code bellow serves the described cases:

You already noticed that after a thumb position has been updated, there is a call of UpdateTrack() method. The method sets TrackRect clipping. To calculate the width between the thumbs, I transform the both thumbs poistion, subtract the right X from the left X and set the result to the clipping rectangle:

The RangeSelector is ready to use. The source code is available at github. Happy coding!