⬆️ ⬇️

Migrating an application from Windows 8 to Windows 8.1

Migrating applications to a new version of the operating system is always a difficult question. Finding the right balance between introducing new functionality, maintaining code, and having a target audience is key.







All these parameters are individual for each project, and in a certain sense depend on each other.



For example, Windows Store allows you to host different builds of applications for Windows 8 and Windows 8.1: applications built under W8 run on W8.1, but not vice versa. You can invest your efforts in adding the necessary new functionality to the W8 build, which will be available both to those who have been updated and to those who have not yet done so, receiving the entire audience at once and delighting it with new amenities. Or you can invest in adding new features only under W8.1, which can be much simpler (which means you can do more good for users), but the W8 audience will not receive any updates.

')





The picture above shows these two conditional strategies - both assuming that you already have some kind of application for W8. In many cases, the upper strategy will be correct: freeze the version under W8 - and start developing the version under W8.1.



Although, of course, there may be scenarios when it is more cost-effective to postpone the freezing to a later period. Here you need to estimate how many users you will have time to catch during the migration (the graph is rather conditional):







Obviously, sooner or later, most users will switch from Windows 8 to Windows 8.1, but the specific speed of the transition may depend on many parameters: from the availability of the Internet in the region to it-policies within the organization. Accordingly, for example, from the point of view of monetization, you need to ask yourself: what is the volume of the market inside Windows 8 (without updating), given the decreasing dynamics.



And another thing: depending on the specific functionality of the application, perhaps you are more than enough with the capabilities of Windows 8 ...



What is important to consider



In the context of the transition from Windows 8 to Windows 8.1, you should also consider the following "nuances":





How to migrate an application



First of all, you will need Windows 8.1 and Visual Studio 2013 for the migration. As soon as you start your project for W8 in the new studio, you will be automatically asked to update the application under W8.1:







Here you will be offered to read about new features in Windows 8.1 and learn about the intricacies of code migration . I recommend to pay attention to the fact that part of the API is marked as obsolete and may stop working.



In order to “redirect” the projects of your solution under Windows 8.1, it is enough to select the corresponding item in the context menu of each project:







After the implementation of this procedure, I recommend trying to build a project and make sure that everything works. It is also worth noting that, in fact, only the project files and the application manifest are automatically updated.



Performance



For the curious, I also advise you to experiment with how the application works before and after retargeting. To do this, in VS2013, you can get into the debugging and find the item “Performance and Diagnostics” there, after which you can choose the appropriate test:







For example, let's compare the responsiveness of a XAML interface. As a guinea pig, I will use the application " Learning Windows 8 ".



Results of Windows 8 application on Windows 8.1:







Here, much time at first takes both parsing appx.xaml, and the actual processing of the application pages.



But the results of the same application after redirecting to Windows 8.1 (and without changing the code) on the same scale:







(You can ignore the pause between pages, except that the small spike in the middle is the scrolling of the GridView.)



Not a bad improvement, is it?



Display application on the screen



Applications on Windows 8 could work in three modes: Fill, Full, and Snapped.







In Windows 8.1, applications (more precisely, the user) have much more flexibility in positioning on the screen - and they can occupy any width up to 500px (by default) or 320 (optional).



However, if the application was built under Windows 8, if there is not enough space, it will be displayed in Snapped View with gray bars on the sides (compatibility mode):







As soon as you redirect the application under Windows 8.1, it will immediately begin to use the general (Full) view of the width of the display up to 500px:







In this place, you should think about how your application behaves in such a fairly narrow space! Please note that it must remain fully functional.



Step back: what happened to our Snapped View? By default, after migration (and for new projects), the minimum supported width is 500px for applications. You can indicate in the manifest that your application does well with 320px:







In this case, between 320 and 500px, your application will switch to what was previously called Snapped view:







Here you need to think again, re-read the migration instructions and understand that you now have deprecated code in your project.



So far it works, but it can break - you obviously should change it / update it. For example, in our project all pages are based on the class LayoutAwarePage, which was previously included in the standard template. In it you can find the following code:



public virtual void InvalidateVisualState() { if (_layoutAwareControls != null) { string visualState = DetermineVisualState(ApplicationView.Value); /*    */ foreach (Control layoutAwareControl in _layoutAwareControls) { VisualStateManager.GoToState(layoutAwareControl, visualState, false); } } } 




The line with the extraction of the state from the ApplicationView is now obsolete - inside DetermineVisualState, a string value was taken from the Value field. In Windows 8.1, you need to switch the state depending on the available width of the application:



  protected virtual string DetermineVisualState() { var windowWidth = Window.Current.Bounds.Width; var windowHeight = Window.Current.Bounds.Height; string viewState; if (windowWidth < 500) { viewState = "Snapped"; } else if (windowWidth < windowHeight) { viewState = "FullScreenPortrait"; } else { viewState = "FullScreenLandscape"; } return viewState; } 




Here I removed the parameters from the DetermineVisualState function, and inside it I had to add an explicit choice of state depending on the width and height of the window.



By the way, since both functions are virtual, perhaps somewhere inside your project, you also additionally updated the logic of mode switching. Probably you should use the search ... or a great opportunity for VS2013 to see where else in the project a specific method is used:







We test, make sure that everything works.



Search



The next important point of our migration program is search. In Windows 8.1, we took into account two things:





Therefore, we now have a beautiful “powered by Bing” search that combines file, web, store and application search :







... and the recommendation to implement search inside the application using SearchBox.



Perhaps you, like us, updating applications, are worried about what happened to the Search contract? It is still present and works for your application when it is running:







However, as you can see in the screenshot above, by default, it searches everywhere, and not in your particular application. From the drop-down list, you can switch to the application:







In order for switching to occur immediately automatically, it is necessary that the search contract, or rather SearchPane, be activated directly from the application. To do this, you need to make quite a bit of effort: add a search button and hang an event on it.



For convenience, I recommend immediately wrapping a button in a UserControl, since you will need to paste it into almost all pages of your application.



Our button looks like a search icon in a circle:







This is a regular button (Button) with the desired symbol inside (& # xE11A;), the correct font (Segoe UI Symbol), and selected styles.



 <UserControl x:Class="EventsApp.UserControls.SearchButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EventsApp.UserControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <Grid> <Button x:Name="searchButton" Content="searchIconCodeHere" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" FontFamily="Segoe UI Symbol" Margin="0" FontSize="24" Tapped="searchButton_Tapped" FontWeight="Normal"> ... </Button> </Grid> </UserControl> 




By clicking on the button, the corresponding event is triggered:



  private void searchButton_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e) { Windows.ApplicationModel.Search.SearchPane.GetForCurrentView().Show(); } 




It remains to insert a button on the application pages. Now when you activate the search from the application, SearchPane is shown with the correct settings.







By the way, I recommend adding such a button even for applications compiled under Windows 8 -> it will continue to work correctly for users under Windows 8.1, if you don’t provide them with a separate assembly.



Searchbox



Naturally, you can make the search even closer to the user. To do this, you can add a SearchBox control to the application , which will allow you to search right inside the application without switching to the additional panel. It should be noted that the SearchBox API is very similar to that for working with SearchPane.



Also, as with the button for calling the search bar, the easiest way would be if you wrap the SearchBox inside your own UserControl — in this case, you can easily integrate all the logic into it, and only insert a control onto the pages.



 <UserControl x:Class="EventsApp.UserControls.LearnSearchBox" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:EventsApp.UserControls" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" > <Grid> <SearchBox x:Name="searchBox" Width="300" Height="48" QuerySubmitted="searchBox_QuerySubmitted" /> </Grid> </UserControl> 




And further in the code:



  private void searchBox_QuerySubmitted(SearchBox sender, SearchBoxQuerySubmittedEventArgs args) { var frame = Window.Current.Content as Frame; frame.Navigate(typeof(SearchPage), args.QueryText); } 




By the way, this code is almost the same as that used when sending a request to SearchPane. To be precise, I copied it from there.



The next step is to insert our new control in all the right places:







Here your can trap an error that is difficult to understand at once (especially if you don’t read the documentation):







The thing is, you can't use SearchPane and SearchBox at the same time. You will need to choose one. In my case, I comment on all the lines referring to SearchPane.



One of the reasons for this conflict is undoubtedly duplication of functionality, another one is that both search engines are tied to the same system hint mechanism (controlled in the OS settings):







Similar to working with SearchPane, you can add your own tips. You can also easily add search activation by typing from the keyboard on the screen:



 <SearchBox x:Name="searchBox" Width="300" Height="48" QuerySubmitted="searchBox_QuerySubmitted" FocusOnKeyboardInput="True" /> 




An example of use can be found at code.msdn.microsoft.com .



Live tiles



Another thing to pay a little attention to is live tiles. In Windows 8, the application could implement tiles of two sizes: square 150x150px and wide 310x150px. In Windows 8.1, they added two more square sizes: a small 70x70px and a large 310x310px.



To add their support to the application, you need to do two key manipulations:



1. Prepare static images:







and specify them in the application manifest:







As well as for Windows 8, if you wish, you can provide the application with images of tiles for different scaling modes (depending on DPI).



2. Update the live tile generation code to include new templates. Let us dwell on this in a bit more detail.



As you may know, ready - made XML templates are available for specifying live tiles that are accessible through the corresponding APIs. In some cases, it may be more convenient to work with them as with text, especially when you need to update templates for several tile sizes at once, as in our case.



Our update tiles look something like this:



  public void UpdateImageTile() { var xml = new XmlDocument(); xml.LoadXml( string.Format( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <tile> <visual branding=""none""> <binding template=""TileSquareImage""> <image id=""1"" src=""{0}"" alt=""{1}""/> </binding> <binding template=""TileWidePeekImage03""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> </visual> </tile>", Entity.Thumbnails.OrderByDescending(x => x.Width).FirstOrDefault().Url, Entity.Title)); TileUpdateManager.CreateTileUpdaterForApplication().Update(new TileNotification(xml)); } 




In this case, we just show a preview image of one of the reports on the live tile. In the case of a wide tile, we use an animation template. Patterns for square and wide tiles are collected in one line.



To add a large square tile, we need:



The result should be something like this:



  public void UpdateImageTile() { var xml = new XmlDocument(); xml.LoadXml( string.Format( @"<?xml version=""1.0"" encoding=""utf-8"" ?> <tile> <visual branding=""none"" version=""2""> <binding template=""TileSquare150x150Image"" fallback=""TileSquareImage""> <image id=""1"" src=""{0}"" alt=""{1}""/> </binding> <binding template=""TileWide310x150PeekImage03"" fallback=""TileWidePeekImage03""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> <binding template=""TileSquare310x310ImageAndText01""> <image id=""1"" src=""{0}"" alt=""{1}""/> <text id=""1"">{1}</text> </binding> </visual> </tile>" , Entity.Thumbnails.OrderByDescending(x => x.Width).FirstOrDefault().Url, Entity.Title)); TileUpdateManager.CreateTileUpdaterForApplication().Update(new TileNotification(xml)); } 




Done!



By the way, in Windows 8.1 you can add the display of live tiles also through the manifest:







Summing up







So why is it worth updating an application under Windows 8.1? Firstly, this performance increase even without updating the code simply due to the fact that many controls were optimized in W8.1. Secondly, these are all new features, including new tile sizes, new controls, and new APIs. Third, it takes into account changes in the operating system itself: in particular, the modes of displaying applications on the screen and the search behavior.



What you need to do to update:

  1. To redirect the project in VS2013 from Windows 8 to Windows 8.1
  2. Update the logic of switching the display modes of the application so that it depends on the size of the “window” and the ratio of width and height, rather than specific states (full, fill, snapped) and orientation of the device.
  3. Update search activation:
    • a. If a search contract was used, at least add an activation button within the application
    • b. Try to search inside an application using SearchBox
  4. Add new tile sizes
    • a. Draw two more sizes of static tiles
    • b. Update live tile generation code.




Further improvements are at your discretion. Successful migration!

Source: https://habr.com/ru/post/202562/



All Articles