Numeric Keypad in WP 8.1

Received my first support case on my app last week. A user from Russia couldn’t create an expense. To me a bit surprising, since it has been used for a couple of years and no one else have had this issue (to my knowledge). I asked him to write down step by step what he did. When I tried the same procedure, I couldn’t re-produce the problem. It worked very well on my mobile. He mailed me a video showing exactly what he did to make the app crash. This was video was extremely helpful and I immediately suspected what the problem could be. The format of number wasn’t consistent; it was displayed with a comma as decimal separator but he entered it with a dot as decimal separator.

In the page where the problem occurs, I use TextBoxes for numeric fields. A nice feature of TextBox is that you can set the type of input with a parameter called InputScope. This property determines which keyboard layout will be used when the user enters a value. I use Number which let the user to enter values with a numeric keypad.

When have tested my app I have always had a keypad with the right sign of the decimal separator. I have tested the app in a couple of different languages but never had a keypad with wrong decimal separator (unfortunately).

My first question was how do I select which decimal separator sign should be on the keypad? I couldn’t find any API so currently I don’t know how to do it from the code (if anyone knows, please leave a comment). I found out two other ways:

  1. Change keyboard in phone settings.
    By selecting a keyboard for a language that uses another decimal separator I managed to change it.
  2. Long tap on the decimal separator.
    If you long tap the decimal sign, you get a box where you can select which sign to use. You can also select the minus sign if you want to enter a negative number.

NumericKeyLongTapBlogg

The work around for my user was to long tap and select the right decimal separator. While testing this, I realized that many of my users might very well have a keypad with the wrong decimal separator as default. I also found it a bit awkward to enter a decimal separator with long tapping, so in my next version I will simply this.

DeviceFamily

During runtime I can check which device family the application is running on with a call to:


string deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;

The function seems to return a so called “magic” string and I haven’t found any list of valid values published by Microsoft. What values does it return? Is there perhaps a better alternative to figure out what device my app is running on? It’s quite important to know since I will make decisions based on the family type. I also would like some type checking during compile time to ensure that I have used a correct value.

I found a page on Microsoft site called “Guide to Universal Windows Platform (UWP) apps” that is referred to whenever I search on TargetDeviceFamily/DeviceFamily or similar. From this page I conclude that there are six families, but still not fully sure how they are identified by above function. While debugging my desktop and mobile and found out two values, “Windows.Desktop” and “Windows.Mobile”. From various sources (contradictory) on Internet, I think the following additional values are used “Windows.Team“, “Windows.IoT“, “Windows.Xbox” and “Windows.Holographic“. Haven’t found a good way to test this. Anyway, I created a utility class that returns an enumeration instead of a magic string (not sure it is 100% correct though).

public static class DeviceFamilies
{
   public static DeviceFamilyType GetCurrentDeviceFamily()
   {
      string deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;

      switch (deviceFamily)
      {
         case "Windows.Desktop":
            return DeviceFamilyType.Desktop;
         case "Windows.Mobile":
            return DeviceFamilyType.Mobile;
         case "Windows.Team":
            return DeviceFamilyType.Team;
         case "Windows.IoT":
            return DeviceFamilyType.IoT;
         case "Windows.Xbox":
            return DeviceFamilyType.Xbox;
         case "Windows.Holographic":
            return DeviceFamilyType.HoloLens;
         default:
            return DeviceFamilyType.Unknown;
      }
   }
}

public enum DeviceFamilyType
{
   Desktop,
   Mobile,
   Team,
   IoT,
   Xbox,
   HoloLens,
   Unknown
}

MainPage

Much of my inspiration to the application shell comes from Microsoft’s news and financial apps. I have used them on both my mobile and desktop and like the way I interact with them. It is also very easy to create a main page with similar user experience in UWP.

The devices have different screen sizes and I want to adopt the main page depending on size available. Not sure I will support all functionality on all devices and there might be some native behavior I need to consider (for example the back button).

For the desktop client I have both space and resource available. For these devices I can offer almost all features and also make them more apparent in the UI.

MainPageDesktop

The mobile devices have smaller screens and restrictions. I need to be more selective with what features to offer and also to present the information in a way more suitable for the smaller screen size.

MainPageMobile

The SplitView control is perfect for this type of layout. There are different ways to adjust the XAML views for different screen sizes and devices.

I can use Visual State Triggers in XAML. It’s a technique to adapt the UI based on the size of the window. Another way is to use the DeviceFamily-{type} feature. In this approach I can create a particular XAML view per device family. All device specific views will share the same presentation logic (code behind).

I’m still in the beginning of this journey, but I suspect that there will be many differences between in how the views will look on each device. I also think it will be clutter to write one XAML view with a lot of state triggers adjusting it for each device family. Therefore, I decided to create a XAML view per device family (with shared presentation logic) and to separate them by a DeviceFamily folder. Source code is available here.

PrototypeSolutionExplorer

The XAML for the desktop’s MainPage is

<Page
    x:Class="UWP.Prototype.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWP.Prototype.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <RelativePanel Grid.Row="0" Background="LightGray">
            <Button Name="btnNavigator" 
                    Background="LightGray"
                    FontFamily="Segoe MDL2 Assets" 
                    Content="&#xE700;" 
                    FontSize="24"
                    Margin="2,6,6,0"
                    Click="btnNavigator_Click"
                    RelativePanel.AlignLeftWithPanel="True"></Button>
            <CommandBar Name="cmdbarToolbar" RelativePanel.RightOf="btnNavigator">
                <AppBarButton Name="cmdbtnBack"  Icon="Back" Label="Back" />
                <AppBarButton Name="cmdbtnForward" Icon="Forward" Label="Forward"/>
                <AppBarSeparator Name="cmdsepNavigationCrud"></AppBarSeparator>
                <AppBarButton Name="cmdbtnRefresh" Icon="Refresh" Label="Refresh"/>
                <AppBarButton Name="cmdbtnClear" Icon="ClearSelection" Label="Clear"/>
                <AppBarButton Name="cmdbtnSave" Icon="Save"  Label="Save" />
                <AppBarButton Name="cmdbtnAdd" Icon="Add"  Label="Add" />
                <AppBarButton Name="cmdbtnEdit" Icon="Edit"  Label="Edit" />
                <AppBarButton Name="cmdbtnDelete" Icon="Delete" Label="Delete"/>
                <AppBarSeparator Name="cmdsepCrudCancel" ></AppBarSeparator>
                <AppBarButton Name="cmdbtnCancel" Icon="Cancel"  Label="Cancel"/>
            </CommandBar>
        </RelativePanel>
        <SplitView Name="spvwNavigator"
                    Grid.Row="1"  
                    DisplayMode="CompactOverlay"  
                    OpenPaneLength="200"  
                    CompactPaneLength="52"  
                    HorizontalAlignment="Left">
            <SplitView.Pane>
                <ListBox SelectionMode="Single"  
                          Name="lbNavigator">
                    <ListBoxItem Name="lbiHomePage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE10F;" />
                            <TextBlock Text="Home" FontSize="20" Margin="20,0,0,2" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiEventPage">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/Assets/EventIcon.png" Height="Auto" Width="24" Margin="0,0,0,0" HorizontalAlignment="Left"></Image>
                            <TextBlock Text="Event" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiAboutPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE171;" />
                            <TextBlock Text="About" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiBuyPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE719;" />
                            <TextBlock Text="Buy" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                </ListBox>
            </SplitView.Pane>
            <SplitView.Content>
                <Frame Name="frmContent">
                </Frame>
            </SplitView.Content>
        </SplitView>
    </Grid>
</Page>

The XAML for the mobile’s MainPage is very similar. The risk with current approach is obliviously a lot of duplicated code, and I need to write more code before I really know the best way to design the views. A view per device family or many visual state triggers….

<Page
    x:Class="UWP.Prototype.Views.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UWP.Prototype.Views"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
    <Page.BottomAppBar>
        <CommandBar Name="cmdbarToolbar" RelativePanel.RightOf="btnNavigator">
            <AppBarButton Name="cmdbtnSave" Icon="Save"  Label="Save" />
            <AppBarButton Name="cmdbtnAdd" Icon="Add"  Label="Add" />
            <AppBarButton Name="cmdbtnEdit" Icon="Edit"  Label="Edit" />
            <AppBarButton Name="cmdbtnDelete" Icon="Delete" Label="Delete"/>
            <AppBarButton Name="cmdbtnCancel" Icon="Cancel"  Label="Cancel"/>
        </CommandBar>
    </Page.BottomAppBar>

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <RelativePanel Grid.Row="0" Background="LightGray">
            <Button Name="btnNavigator" 
                    Background="LightGray"
                    FontFamily="Segoe MDL2 Assets" 
                    Content="&#xE700;" 
                    FontSize="24"
                    Margin="0,0,0,0"
                    Click="btnNavigator_Click"
                    RelativePanel.AlignLeftWithPanel="True"></Button>
        </RelativePanel>
        <SplitView Name="spvwNavigator"  
                    Grid.Row="1"  
                    DisplayMode="Overlay"  
                    OpenPaneLength="200"  
                    CompactPaneLength="56"  
                    HorizontalAlignment="Left">
            <SplitView.Pane>
                <ListBox SelectionMode="Single"  
                          Name="lbNavigator">
                    <ListBoxItem Name="lbiHomePage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE10F;" />
                            <TextBlock Text="Home" FontSize="20" Margin="20,0,0,2" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiEventPage">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/Assets/EventIcon.png" Height="Auto" Width="24" Margin="0,0,0,0" HorizontalAlignment="Left"></Image>
                            <TextBlock Text="Event" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiAboutPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE171;" />
                            <TextBlock Text="About" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                    <ListBoxItem Name="lbiBuyPage">
                        <StackPanel Orientation="Horizontal">
                            <TextBlock FontFamily="Segoe MDL2 Assets" FontSize="24" Margin="0,0,0,0" Text="&#xE719;" />
                            <TextBlock Text="Buy" FontSize="20" Margin="20,0,0,0" />
                        </StackPanel>
                    </ListBoxItem>
                </ListBox>
            </SplitView.Pane>
            <SplitView.Content>
                <Frame Name="frmContent">
                </Frame>
            </SplitView.Content>
        </SplitView>
    </Grid>
</Page>

Mobilize.NET

From the build event earlier this year I heard about a tool, Mobilize.NET, too relieve the work load to migrate an app from Silverlight to UWP. There is a good web cast from channel 9 about it at https://channel9.msdn.com/Events/Build/2016/P498. I really liked the idea even though I suspected that the tool wouldn’t be able to convert so much of my app. But just to get some help with some well-known common tasks sounded very helpful. So I installed it and gave it a try.

There were many issues reported and it would take very long time to sort things out (if even doable). As I looked through the converted code I realized that I’m just trying to port the code. My current implementation is just intended as an app for windows phone. It’s not designed as a universal app capable of running on several different devices.

I wanted to change this! Instead of just porting my “windows phone 8.1-ish” user interface to the universal windows platform. I wanted to re-design it so it becomes “universal-ish” and able to run on several different devices, primarily desktops and phones. Also, cross-platform in the long run.

Didn’t get so much help from Mobilize.NET and now my next challenge is to find a universal user interface, easy to use, implement and maintain for all different kind of devices…. Let’s see what I will end up with.

AutoMapper 5.0.2

I’m migrating my app from Silverlight to UWP. At the same time, I’m changing from VS 2013 to VS 2015. It was a while since I worked with the app and noticed that there where a new version of AutoMapper available in Nuget Package Manager, but I couldn’t install it. I tried to find a solution on the Internet, but didn’t find any. After several hours of struggling, I managed to install it after removing the contents of both bin and obj folders from all projects in my solution. I tried several times to just remove from bin, but wasn’t enough.

Upgrade to NHibernate 3.0.0

I recently upgraded to NHibernate 3.0.0. NHibernate 3.0.0 has a good backward compatible with version 2.1.2. It includes a new Linq provider that fully supports Linq. When upgrading to NHibernate 3.0.0 I stumble into the following issues:

· The new Linq provider is included in NHibernat 3.0.0 and I didn’t have to download it separately.

· The method session.Linq<T>() is replaced by session.Query<T>().

· The new Linq provider has full support for Linq and I had to update some Linq queries. For example, it manages eager load differently. It includes new methods, Fetch and FetchMany, to define what shall be fetched eagerly.

So, it was quite easy to upgrade and I didn’t have that much trouble. Still need to explore all new features and re-factor the code whenever possible to take advantage of them. First impression of NH 3.0.0 is very good.

IE crashes when opening document in Sharepoint

For some reason my browser started to crash when I tried to open documents in Sharepoint. After some investigation I found out that I had multiple versions of an assembly called Owssupp.dll confusing IE. One version from Office 2003 and another from Office 2007. The later one was installed while evaluating Onenote 2007. I solved the problem by uninstalling Onenote 2007. I found a link that describes the problem http://geekswithblogs.net/redwards/archive/2007/06/18/113287.aspx. Additional information can be found here http://support.microsoft.com/kb/833714.

Exception has been thrown by the target of invocation

I was leading a lab today. The first exercise has a starting solution with some basic code that you are suppose to enhance during the implementation. One of the very first thing you shall do is to run the unit tests to make sure that the code works. It has always worked! That is, until today. One of the participants couldn’t execute any of unit tests. Visual Studio kept on displaying the same error message for every attempt to run any of the unit tests: “Exception has been thrown by the target of invocation”.

We searched on the Internet and found many suggestions on what might cause the problem. Finally we found out that the reason was that his development environment wasn’t connected to TFS. The lab is of course checked into TFS and there is a bug in VS 2008 that causes this problem if you open a bounded solution in a studio disconnected from TFS (http://blogs.msdn.com/b/shitals/archive/2009/12/31/9942725.aspx).

Troubleshooting NHibernate

There are many different ways to troubleshoot NHibernate. I mainly use show_sql, log4net and SQL Server Profile.

show_sql

In the configuration of NHibernate, there is a property called show_sql. If you set this to true, NHibernate will output all generated sql to the console.

You enable show_sql by adding the following piece of code to the configuration file.

<property name=”show_sql”>true</property>

To view the output from a unit test, you must select the unit test in the Test Result window and use View Test Result Details.

The unit test’s result window displays the output.

log4Net

If you need more detailed debug information you can use log4net. Log4Net is an open source library that NHibernate uses to log all interesting events. You can use it to log information to a file, the console or both. To use it, you have to add some information to the configuration file. First declare the log4net section.

<configSections>
<section name=”hibernate-configuration” type=”NHibernate.Cfg.ConfigurationSectionHandler, NHibernate” />
<section name=”log4net” type=”log4net.Config.Log4NetConfigurationSectionHandler, log4net”/>
</configSections>

Here is an example how you can configure log4net to write events from NHibernate both to a file and the console. Read more about log4net on the homepage.

<log4net>
<appender name=”NHibernateFileLog” type=”log4net.Appender.RollingFileAppender”>
<file value=”c:\nhibernate2.txt” />
<appendToFile value=”true” />
<rollingStyle value=”Size” />
<maxSizeRollBackups value=”10″ />
<maximumFileSize value=”100KB” />
<staticLogFileName value=”true” />
<layout type=”log4net.Layout.PatternLayout”>
<conversionPattern value=”%d{HH:mm:ss.fff} [%-5p] %c – %m%n” />
</layout>
</appender>
<appender name=”Console” type=”log4net.Appender.ConsoleAppender, log4net”>
<layout type=”log4net.Layout.PatternLayout,log4net”>
<param name=”ConversionPattern” value=”%d{ABSOLUTE} %-5p %c{1}:%L – %m%n” />
</layout>
</appender>
<root>
<level value=”DEBUG”/>
<appender-ref ref=”Console” />
</root>
<logger name=”NHibernate” additivity=”false”>
<level value=”DEBUG”/>
<appender-ref ref=”NHibernateFileLog”/>
<appender-ref ref=”Console” />
</logger>
</log4net>

You also have to initialize log4net from the application

//Start Log4Net
log4net.Config.XmlConfigurator.Configure();

The output now contains much more information about the internal works of NHibernate:

SQL Server Profiler

SQL Server Profiler can be very useful when you line step an application and want to view each database call NHiberante makes. In this way you can follow how NHibernate flushes changes to the database and manages caching. SQL Server Profiler can be started from SQL Server Management Studio.

To use it your user must be a member of sysadmin.

When the Profiler is started, you can create a new trace and view each database call NHibernate makes.

Slow Menus in VS 2010

In one of my assignment they use VS 2010 and I recently had to install it. My first impression wasn’t very good. The menus in VS 2010 were extremely slow. Tried different settings in the environment but nothing helped. I looked if Google could give me any answer, and it could! It turned out that my computer was configured to use 16 bit colour quality. By increasing it to 32-bit, the problem went away.