Blog

posts by Fons Sonnemans

Fons Sonnemans 2019 Development Tools List

0 Comments
By Fons Sonnemans, 20-nov-2019

Many years ago Scott Hanselman wrote the famous Scott Hanselman Ultimate Tools List post. Now it is time to write my own list because there are new tools. I'm an App developer more than a Web developer so I use different tools. I write mainly XAML (UWP and WPF) apps and only occasionally an ASP.NET website. My code is written in C#. I create them because it is fun to do and it helps me to train my own skills. I use this experience for my trainings (C#, XAML, ASP.NET and SQL). I write my own training material so I need the experience. I have about 40 Windows apps in the Store, some are very popular. The apps have almost 5 million downloads and daily thousands of players. Most of my apps are free but there are Ads in it to generate some revenue.

Software

  • Visual Studio is my favorite IDE, version 2019. I use it for coding (mainly C# but occasionally also JavaScript and TypeScript), debugging and XAML/HTML/CSS editing. I think 75% of my development time is with Visual Studio.
  • Blend for Visual Studio is installed with Visual Studio. I use it for designing the XAML of my UWP and WPF apps. Compared to Visual Studio, Blend has a better Assets panel, Resource management, Data management, Animations, States and Templating & Styling editing. Most developers don't use it and that is a pitty. You should give it a try. You can write XAML way better and faster with Blend.
  • Microsoft Expression Design is a great tool for creative professionals and developers who want to build graphics for application user interfaces, the web, or any other medium. It is an alternative for Adobe Illustrator. I use it for my graphic assets (logo's, images, paths) in my apps. It is a vector drawing tool which you can use to export your graphics to XAML paths. It is really nice. This tool used to be a paid app shipped in Microsoft Expression Studio in the good old Silverlight days. It is now a free download. I wish it was Open Source. I would love to add some extra features to it.
  • Microsoft Expression Encoder is an advanced application for bringing your edited video project to the web for high-quality playback. I use it to edit app promo video's. I record the videos using the Xbox Game Bar.
  • Paint.NET is great for image and photo editing. You can download it or install it from the Microsoft Store.
  • 7-Zip - The best app to create or unpack archives (zip, rar, etc). Very fast, free and open source.
  • Notepad++ is a free (as in “free speech” and also as in “free beer”) source code editor and Notepad replacement that supports several languages. 
  • FreeFileSync FreeFileSync is a folder comparison and synchronization software that creates and manages backup copies of all your important files. Instead of copying every file every time, FreeFileSync determines the differences between a source and a target folder and transfers only the minimum amount of data needed. I use it to keep my desktop and laptops in sync. 
  • ZoomIt is a screen zoom and annotation tool for technical presentations that include application demonstrations. I use it a lot in my trainings and presentations.
  • Microsoft Office is great and I use it a lot. I use PowerPoint for my slides, OneNote for my notes and Outlook for my mails. I don't like Word but I have no better alternative. Excel is great but I don't have to use it a lot. I love that OneNote syncs all my notes on every computer and my phone.
  • PowerRename Power Toy is a Windows Shell Extension for advanced bulk renaming using search and replace or regular expressions. PowerRename allows simple search and replace or more advanced regular expression matching.
  • Steps Recorder (called Problems Steps Recorder in Windows 7), is a program that helps you troubleshoot a problem on your device by recording the exact steps you took when the problem occurred. You can then send this record to a support professional to help them diagnose the problem. It is already installed on your Windows computer. Just hit Windows+R and type PSR. I wish all my users would use it to report problems to me.
  • Google Chrome and Edge are my favorite browsers. I use Edge based on Chromium which is a smart move from Microsoft. I read PDF files in Chrome, no need to install Adobe Acrobat.
  • NuGet Explorer allows browsing NuGet packages from an online feed and viewing contents of the packages. NuGet is a package management tool in Visual Studio. It is open source and setup by Oren Novotny.
  • XAML Diff Is a tool which generates the UWP Visual State Setters using a diff analysis of your named elements in your XAML. I wrote it myself and published it in the Microsoft Store. I wrote a blog post about it last year. I hope you like it. I find it very useful. 
  • Audacity is an easy-to-use, multi-track audio editor and recorder for Windows, Mac OS X, GNU/Linux and other operating systems. I use it for editing the sounds in my games.
  • Postman is a collaboration platform for Web API (REST & HTTP) development. Postman's features simplify each step of building an API and streamline collaboration so you can create better APIs - faster.
  • Fiddler is the easy, clean, and powerful debugging proxy for checking out HTTP between here and there. It even supports sniffing SSL traffic.
  • Windows Application Driver (WinAppDriver) is a service to support Selenium-like UI Test Automation on Windows Applications. You can write Unit Tests to test the UI of your desktop apps (UWP, WPF, Windows Forms, etc).
  • Try-Convert is a sample tool showing how to build a global tool and also helps you convert projects to .NET Core. The future is .NET Core. 
  • Rufus creates bootable USB drives the easy way.
  • GitHub is the place where I store my repositories. I use GitHub Desktop, Git Extensions and Sourcetree as my git clients.
  • SQL Server Management Studio (SSMS) - SQL Server Management Studio (SSMS) is an integrated environment for managing any SQL infrastructure, from SQL Server to Azure SQL Database.
  • SQL Server Data Tools (SSDT) is a modern development tool for building SQL Server relational databases, Azure SQL databases, Analysis Services (AS) data models, Integration Services (IS) packages, and Reporting Services (RS) reports. With SSDT, you can design and deploy any SQL Server content type with the same ease as you would develop an application in Visual Studio. It is an individual component inside the Visual Studio Installer.

Analyzers

Analyzers where added to Visual Studio 2015. I love this technique and here is a list of analyzers which I use a lot.

  • ClrHeapAllocationAnalyzer - Roslyn based C# heap allocation diagnostic analyzer that can detect explicit and many implicit allocations like boxing, display classes (aka closures), implicit delegate creations, etc. 
  • ReflectionIT Analyzer - I wrote this analyzer myself. It contains a few analyzers and fixes of things I did wrong in my code. Now I can quickly find and fix them. 
  • Microsoft.CodeAnalysis.FxCopAnalyzers Microsoft recommended code quality rules and .NET API usage rules, including the most important FxCop rules, implemented as analyzers using the .NET Compiler Platform (Roslyn). These analyzers check your code for security, performance, and design issues, among others. 
  • WpfAnalyzers Roslyn analyzers for WPF.
  • Meziantou.Analyzer A Roslyn analyzer to enforce some good practices in C#.
  • Rapid XAML Toolkit Tools to accelerate XAML app development. It is even extendable.
  • Security Code Scan Detects various security vulnerability patterns: SQL Injection, Cross-Site Scripting (XSS), Cross-Site Request Forgery (CSRF), XML eXternal Entity Injection (XXE), etc.

 

Visual Studio Extensions

  • ILSpy - Integrates the ILSpy decompiler into Visual Studio. 
  • Web Essentials - Essential tools for writing Web (in my case ASP.NET) apps.
  • XAML Styler is a visual studio extension, which formats XAML source code by sorting the attributes based on their importance. This tool can help you/your team maintain a better XAML coding style as well as a much better XAML readability.
  • Inlining Analyzers shows if a method call will be inlined by the JIT Compiler. Method calls are highlighted right in the source code and also display the reason for a failed inline as given by the JIT Compiler.
  • EF Core Power Tools - I use it to reverse engineer existing databases to Entity Framewok Core
  • ReswPlus - Advanced Resw File Code Generator for UWP apps. ReswPlus is a Visual Studio extension enriching your existing .resw files. Written by Rudy Huyn
  • Open Command Line - Opens a command line at the root of the project.
  • Visual Studio IntelliCode is a set of AI-assisted capabilities that improve developer productivity with features like contextual IntelliSense, argument completion, code formatting, and style rule inference.
  • Concurrency Visualizer for Visual Studio 2017 Visualizes execution history and profiles applications. I hope a VS2019 version will be published soon.
  • Disasmo: VS2019 Add-in. Click on any method to see what ASM JIT will generate for it.
  • Multilingual App Toolkit v4.0 (VS 2017+) helps you localize your Windows and Xamarin Apps by providing file management, translation services, translation editor, and build integration.
  • ReflectionIT.Refactoring - I wrote this extension myself. It contains a few refactorings to speedup my coding.
  • Roslynator - A collection of 500+ analyzers, refactorings and fixes for C#, powered by Roslyn. I don't use it a lot but it is worth to mention.

NuGet Packages

  • Windows Community Toolkit is a collection of helper functions, custom controls, and app services. It simplifies and demonstrates common developer tasks building UWP apps for Windows 10. It is open source and has great documentation. You can also preview the capabilities of the toolkit by isntalling the Windows Community Toolkit Sample App. I use it in almost all of my UWP apps.
  • Microsoft.UI.Xaml (aka WinUI) - This package provides backward-compatible versions of Windows UI features including UWP XAML controls, and Fluent styles and materials. It is part of the Windows UI Library. I use it in all of my UWP apps. The next minor version will also contain the NumberBox control which I proposed. The next major release is WinUI 3.0, it is now already in Alpha. It will allow you to use the UWP controls in .NET (Core/5) as an alternative for WPF. 
  • Newtonsoft.Json (aka Json.NET) is a popular high-performance JSON framework for .NET. I use it for all my JSON work. In .NET Core 3 I switched to System.Text.Json.
  • Microsoft.Xaml.Behaviors.Uwp.Managed - Blend Behaviors and Actions for UWP, open source.
  • Microsoft.Xaml.Behaviors.Wpf  - Blend Behaviors, Actions and Triggers for WPF, open source.
  • WindowsStateTriggers and AdaptiveTriggerLibrar - Collections of custom UWP visual state triggers. 
  • PlayFabAllSDK - I use this for leaderboards in my games.
  • ThomasLevesque.WeakEvent - A generic weak event implementation.
  • Nito.AsyncEx - A helper library for the Task-Based Asynchronous Pattern (TAP).
  • Microsoft.AppCenter - I use it to diagnose the Crashes and track Analitycs events of my UWP apps. The quality of the StackTraces is really great.
  • Microsoft.Services.Store.SDK - The Microsoft Store Services SDK includes advertising and engagement frameworks. The best way to generate revenue in my free games.
  • Win2D.uwp - An easy-to-use Windows Runtime API for immediate mode 2D graphics rendering. I use it in some of my UWP apps. 
  • Microsoft.EntityFrameworkCore and Dapper - My two favorite ORMs. EF is easy and Dapper is fast. I often use them both in a project.
  • xUnit is a developer testing framework, built to support Test Driven Development, with a design goal of extreme simplicity and alignment with framework features. I use it with xunit.runner.visualstudio which integrates it with the Visual Studio Test Explorer.  

Closure

I hope this list is useful for you. Especially if you are also a UWP developer. I will probably write a new one in the future because things will change, as always.

Fons

READ MORE

Using C# 8.0 in Core 2.x, .NET Framework and UWP projects

4 Comments
By Fons Sonnemans, 09-jul-2019

With Visual Studio 2019 Preview (currently version 16.2.0 Preview 3.0) you can use C# 8.0 in  .NET Core 3.0 projects. You only have to set the Language version to C# 8.0 (beta) in the Advanced Build Settings. Make sure you do this for 'All configurations' and 'Any CPU', see screenshot below.

Build Settings

This setting will add a LangVersion property to your .csproj file (line 6).

Core 3.0 project file

Core 2.2, .NET Framework and UWP projects

If you try to set the Language version property in a non .NET Core 3.0 project the dropdown doesn't show the C# 8.0 option.

Adevanced Build Settings

You may think it is not possible to use C# 8.0 in these projects. Luckely you still can but you have to add the LangVersion property manually in the .csproj file (line 6). 

Core 2.2 project file

The same also works in .NET Framework projects (ASP.NET, Windows Forms, WPF, Console, Class Library, etc) and UWP projects (line 5 in both screenshots below). You first have to Unload the project before you can Edit it. Reload the project when you are done. You can also edit it in an external text editor.

.NET Framework project file

UWP project file

Unsupported C# 8.0 features

C# 8.0 comes with a lot of new features which are described in the What's new in C# 8.0 documentation. Unfortunately the Default interface members and Indices and ranges features are only supported in .NET Core 3.0 projects. Still there are enough great features to use.

Closure

This workaround is something Microsoft will fix in a new version of Visual Studio. I expect it will be released together with .NET Core 3.0 on the .NET Conf 2019 (online) event (September 23 — 25, 2019). C# 8.0 is now still in Beta, please don't use if in your production code. Have fun with the new features.

Fons

READ MORE

XAML Markup Extensions

0 Comments
By Fons Sonnemans, 29-apr-2019

The possibility to create your own Markup Extensions where added to UWP in the Windows Falls Creators Update SDK (16299, 1709).  I only used it once. I created an OnDevice Markup Extensions which I added to the Windows Community Toolkit.

Last month Pedro Lamas wrote the blog post Making the case for XAML Markup Extensions. He demonstrates a FontIconExtension which he uses to shorten the XAML of an AppBarButton. I love his solution. His blog post inspired me to write some new Markup Extensions with the same goal, short XAML. 

Demo project

In the following page I have 2 Rectanges, 2 Borders and 2 Buttons inside a vertical StackPanel. The first Rectangle, Border and Button use the traditional (long) XAML syntax. The second ones use the Markup Extension which I created. The XAML is much shorter which makes it for me easier to write and read.

<Page x:Class="XamlMarkupExtensionsDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:XamlMarkupExtensionsDemo"
      xmlns:me="using:XamlMarkupExtensionsDemo.MarkupExtensions"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <StackPanel Spacing="16"
                    Margin="16">
            
            <Rectangle Height="80">
                <Rectangle.Fill>
                    <ImageBrush ImageSource="https://png.pngtree.com/thumb_back/fw800/back_pic/03/70/72/5257b6c12d89875.jpg" />
                </Rectangle.Fill>
            </Rectangle>

            <Rectangle Height="80"
                       Fill="{me:ImageBrush Source='https://png.pngtree.com/thumb_back/fw800/back_pic/03/70/72/5257b6c12d89875.jpg' }" />

            <Border Height="80">
                <Border.Background>
                    <LinearGradientBrush EndPoint="0.5,1"
                                         StartPoint="0.5,0">
                        <GradientStop Color="Red" />
                        <GradientStop Color="Green"
                                      Offset="1" />
                    </LinearGradientBrush>
                </Border.Background>
            </Border>

            <Border Height="80"
                    Background="{me:GradientBrush Start=Red, Stop=Green}" />

            <StackPanel Orientation="Horizontal"
                        Spacing="12">

                <Button Click="ButtonUndo_Click"
                        Width="160"
                        FontSize="32">
                    <Button.Content>
                        <TextBlock>
                            <Run FontFamily="Segoe MDL2 Assets"
                                 FontSize="24"
                                 Text="&#xE7A7;" />
                            <Run Text=" Undo" />
                        </TextBlock>
                    </Button.Content>
                    <Button.KeyboardAccelerators>
                        <KeyboardAccelerator Key="Z"
                                             Modifiers="Control" />
                    </Button.KeyboardAccelerators>
                </Button>

                <Button Content="{me:GlyphAndText Glyph='&#xE7A6;', GlyphFontSize=24, Text='Redo'}"
                        me:KeyboardAcceleratorExtension.KeyboardAccelerator="{me:KeyboardAccelerator Key=Y, Modifiers=Control}"
                        Click="ButtonRedo_Click"
                        Width="160"
                        FontSize="32" />
            </StackPanel>
        </StackPanel>
    </Grid>
</Page>

The Rectangle uses an ImageBrush Markup Extension which reduces 3 lines of XAML markup. The Border uses a GradientBrush Markup Extension which reduces 8 lines of XAML markup. The Button uses a GlyphAndText and a KeyboardAccelerator Markup Extensions which reduces 10 lines of XAML markup. I have set up my Visual Studio/Blend Text Editor to 'position each attribute on a separate line'.

XAML Text Editor Options

This page renders like this:

MainPage

ImageBrush Markup Extension

The ImageBrushExtension can be used to create an ImageBrush with a Source, Stretch and Opacity.

[MarkupExtensionReturnType(ReturnType = typeof(ImageBrush))]
public class ImageBrushExtension : MarkupExtension {

    public string Source { get; set; }
    public Stretch Stretch { get; set; } = Stretch.Fill;
    public double Opacity { get; set; } = 1.0;

    protected override object ProvideValue() {
        return new ImageBrush() {
            Stretch = this.Stretch,
            Opacity = this.Opacity,
            ImageSource = new BitmapImage {
                UriSource = new Uri(Source),
            }
        };
    }
}

GradientBrush Markup Extension

The GradientBrushExtension can be used to create a GradientBrush with Start and Stop colors and points.

[MarkupExtensionReturnType(ReturnType = typeof(GradientBrush))]
public class GradientBrushExtension : MarkupExtension {

    public Color Start { get; set; }
    public Color Stop { get; set; }
    public Point StartPoint { get; set; } = new Point(0.5, 0);
    public Point EndPoint { get; set; } = new Point(0.5, 1);

    protected override object ProvideValue() {
        var gb = new LinearGradientBrush() {
            StartPoint = this.StartPoint,
            EndPoint = this.EndPoint,
        };
        gb.GradientStops.Add(new GradientStop() {
            Color = Start,
        });
        gb.GradientStops.Add(new GradientStop() {
            Color = Stop,
            Offset = 1,
        });
        return gb;
    }
}

GlyphAndText Markup Extension

The GlyphAndTextExtension can be used to create a TextBlock with a Glyph and a Text.

[MarkupExtensionReturnType(ReturnType = typeof(TextBlock))]
public class GlyphAndTextExtension : MarkupExtension {

    public string Glyph { get; set; }
    public double GlyphFontSize { get; set; } = 14;
    public string Text { get; set; }
    public FontFamily FontFamily { get; set; } = new FontFamily("Segoe MDL2 Assets");

    protected override object ProvideValue() {
        var tb = new TextBlock();
        tb.Inlines.Add(new Run {
            Text = this.Glyph,
            FontSize = this.GlyphFontSize,
            FontFamily = this.FontFamily,
        });
        tb.Inlines.Add(new Run { Text = " " + this.Text });
        return tb;
    }
}

KeyboardAccelerator Markup Extension

The KeyboardAcceleratorExtension can be used to a create KeyboardAccelerator with a Key and Modifiers. It also contains a KeyboardAccelerator attached property which allows you to add it to the KeyboardAccelerators collection of a UIElement.

[MarkupExtensionReturnType(ReturnType = typeof(KeyboardAccelerator))]
public class KeyboardAcceleratorExtension : MarkupExtension {

    /// <summary> 
    /// Identifies the KeyboardAccelerator attachted property. This enables animation, styling, binding, etc...
    /// </summary>
    public static readonly DependencyProperty KeyboardAcceleratorProperty =
        DependencyProperty.RegisterAttached("KeyboardAccelerator",
                                            typeof(UIElement),
                                            typeof(KeyboardAcceleratorExtension),
                                            new PropertyMetadata(default(object), OnKeyboardAcceleratorChanged));

    /// <summary>
    /// Gets or sets the virtual key (used in conjunction with one or more modifier keys)
    /// for a keyboard shortcut (accelerator).
    /// </summary>
    public VirtualKey Key { get; set; }

    /// <summary>
    /// Gets or sets the virtual key used to modify another keypress for a keyboard shortcut
    /// (accelerator).
    /// </summary>
    public VirtualKeyModifiers Modifiers { get; set; }

    /// <summary>
    /// Gets the value of the KeyboardAccelerator attached property from the specified FrameworkElement.
    /// </summary>
    public static object GetKeyboardAccelerator(DependencyObject obj) {
        return (object)obj.GetValue(KeyboardAcceleratorProperty);
    }

    /// <summary>
    /// KeyboardAccelerator changed handler. 
    /// </summary>
    /// <param name="d">FrameworkElement that changed its KeyboardAccelerator attached property.</param>
    /// <param name="e">DependencyPropertyChangedEventArgs with the new and old value.</param> 
    private static void OnKeyboardAcceleratorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
        if (d is FrameworkElement source) {
            var value = (KeyboardAccelerator)e.NewValue;
            source.KeyboardAccelerators.Add(value);
        }
    }

    /// <summary>
    /// Returns a KeyboardAccelerator with the Key and Modifiers set
    /// </summary>
    /// <returns></returns>
    protected override object ProvideValue() {
        return new KeyboardAccelerator() {
            Key = this.Key,
            Modifiers = this.Modifiers,
        };
    }

    /// <summary>
    /// Sets the value of the KeyboardAccelerator attached property to the specified FrameworkElement.
    /// </summary>
    /// <param name="obj">The object on which to set the KeyboardAccelerator attached property.</param>
    /// <param name="value">The property value to set.</param>
    public static void SetKeyboardAccelerator(DependencyObject obj, object value) {
        obj.SetValue(KeyboardAcceleratorProperty, value);
    }
}

The code

I have published the code on GitHub. I hope you like it. Maybe it will inspire you too to create Markup Extensions.

Fons

READ MORE

XAML TwoPaneView

0 Comments
By Fons Sonnemans, 05-feb-2019

I'm in the process of learning the new Windows 10 SDK Preview Build 18323. It includes a new control named TwoPaneView. The TwoPaneView is a Panel control which contains two Panes. The Panes are shown next to each other if there is enough room, otherwise below each other. If that is not possible only one pane is shown. You can use it in situations in which you normally used a RelativePanel in combination with some ViewStates to reposition one panel beside or below another depending off the size (AdaptiveTriggers). This was always a lot of work which is now very easy with the new control.

Demo

In my demo app I created a Page with only a TwoPaneView control in it. In Pane1 I placed a Grid with a Red background. In Pane2 I placed a Grid with a Blue background. The Length of the Pane1 is set to star size 2 (similar to a Grid ColumnDefinition Width), Pane2 is set to star size 1. This makes the length (Width or Height depending of the Mode: Wide or Tall) of Pane1 is twice as much than of Pane2. The MinTallModeHeight is set to 450 and the MinWideModeWidth is set to 550. If you run this app and resize the window it will show the two panes above each other when the Height is above 450 and the Width is below 550. If the Width is above 550 it will show the two panes next to each other. If the Height is below 450 and the Width below 550 it will only show one pane, in this case Pane1 which can be altered to Pane2 using the PanePriority property.

Xaml

The TwoPaneView has a Mode property and a ModeChanged event. In this example I have databound the Mode to the Text of a TextBlock using compiled binding (x:Bind).

<Page x:Class="App6.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      RequestedTheme="Dark"
      SizeChanged="Page_SizeChanged"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <TwoPaneView x:Name="twoPaneViewDemo"
                 Pane1Length="2*"
                 Pane2Length="1*"
                 PanePriority="Pane1"
                 MinTallModeHeight="450"
                 MinWideModeWidth="550"
                 TallModeConfiguration="TopBottom"
                 WideModeConfiguration="LeftRight">
        <TwoPaneView.Pane1>
            <Grid Background="Red"
                  Padding="8"
                  Margin="4">
                <StackPanel>
                    <TextBlock Text="Pane 1"
                               Style="{StaticResource HeaderTextBlockStyle}" />
                    <TextBlock x:Name="textBlockPageSize1"
                               Style="{StaticResource TitleTextBlockStyle}" />
                    <TextBlock Text="{x:Bind twoPaneViewDemo.Mode, Mode=OneWay}"
                               Style="{StaticResource TitleTextBlockStyle}" />
                </StackPanel>

            </Grid>
        </TwoPaneView.Pane1>
        <TwoPaneView.Pane2>
            <Grid Background="Blue"
                  Padding="8"
                  Margin="4">
                <StackPanel>
                    <TextBlock Text="Pane 2"
                               Style="{StaticResource HeaderTextBlockStyle}" />
                    <TextBlock x:Name="textBlockPageSize2"
                               Style="{StaticResource TitleTextBlockStyle}" />
                    <TextBlock Text="{x:Bind twoPaneViewDemo.Mode, Mode=OneWay}"
                               Style="{StaticResource TitleTextBlockStyle}" />
                </StackPanel>
            </Grid>
        </TwoPaneView.Pane2>
    </TwoPaneView>
</Page>

Code Behind

The code behind has the has the Page_SizeChanged method which displays the size of the page in the Text of the textBlockPageSize1 and textBlockPageSize1 controls.

public sealed partial class MainPage : Page {
    public MainPage() {
        this.InitializeComponent();
    }

    private void Page_SizeChanged(object sender, SizeChangedEventArgs e) {
        textBlockPageSize1.Text = textBlockPageSize2.Text
                                = e.NewSize.ToString();
    }
}

TwoPaneView in the Windows UI Library (WinUI)

The TwoPaneView is only available in the new Windows SDK Preview. If you are not creating an app with the minimum target version set to this latest SDK you can't use the TwoPaneView. Luckily there is an easy solution (workaround) for this. There will be a TwoPaneView included in the Windows UI Library (WinUI). You can then also use it in project which support the 14393 to 17134 SDK's. You can already try it out using the latest preview version which is available on NuGet.

Closure

I will use the TwoPaneView a lot in my apps. I expect you will do it too.

Fons

READ MORE

XAML StandardUICommand.Kind

0 Comments
By Fons Sonnemans, 27-nov-2018

I'm in the process of learning the new Windows SDK Preview. This SDK has made it possible to set the Kind property of a StandardUICommand. The StandardUICommand was added in the 1809 SDK (17763) but the StandardUICommandKind property was readonly which made it impossible to use from XAML. You could only set the Kind using a constructor parameter in code. Now you can define the StandardUICommand in XAML inside your AppBarButton, MenuFlyoutItem and MenuBarItem.

Demo

I have created a small demo page with a CommandBar and a DropDownButton (also new in the 1809 SDK). The CommandBar has 2 AppBarButton controls (Undo & Redo). The Command property of these buttons are set to a StandardUICommand with the Kind values 'Undo' and 'Redo'. The DropDownButton has a flyout menu with 3 FlyoutMenuItems in it. The Commands of these items are also set to a StandardUICommands. The StandardUICommand will set the Icon, Label/Text, Tooltip and KeyboardAccelerator of the button/item.

The possible value for Kind are:

  • None
  • Cut
  • Copy
  • Paste
  • SelectAll
  • Delete
  • Share
  • Save
  • Open
  • Close
  • Pause
  • Play
  • Stop
  • Forward
  • Backward
  • Undo
  • Redo

The XAML of the page

<Page x:Class="App3.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App3"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="1*" />
        </Grid.RowDefinitions>
        <CommandBar DefaultLabelPosition="Right">
            <AppBarButton>
                <AppBarButton.Command>
                    <StandardUICommand Kind="Undo" />
                </AppBarButton.Command>
            </AppBarButton>
            <AppBarButton>
                <AppBarButton.Command>
                    <StandardUICommand Kind="Redo" />
                </AppBarButton.Command>
            </AppBarButton>
        </CommandBar>


        <DropDownButton Content="File" Margin="8" 
                                      Grid.Row="1" VerticalAlignment="Top">
            <DropDownButton.Flyout>
                <MenuFlyout>
                    <MenuFlyoutItem>
                        <MenuFlyoutItem.Command>
                            <StandardUICommand Kind="Open" />
                        </MenuFlyoutItem.Command>
                    </MenuFlyoutItem>
                    <MenuFlyoutItem>
                        <MenuFlyoutItem.Command>
                            <StandardUICommand Kind="Save" />
                        </MenuFlyoutItem.Command>
                    </MenuFlyoutItem>
                    <MenuFlyoutItem>
                        <MenuFlyoutItem.Command>
                            <StandardUICommand Kind="Delete" />
                        </MenuFlyoutItem.Command>
                    </MenuFlyoutItem>
                </MenuFlyout>
            </DropDownButton.Flyout>
        </DropDownButton>
    </Grid>
</Page>

Closure

It is great that the Kind property can now be set. This saves me a lot of work setting the Icon, Label/Text, Tooltip and KeyboardAccelerator of AppBarButtons and MenuItems manually.

Fons

READ MORE

XAML ComboBox IsEditable and Text Properties

2 Comments
By Fons Sonnemans, 12-sep-2018

I'm in the process of learning the new Windows SDK Preview. Today's subject is the new IsEditable and Text properties of the ComboBox control.

Demo

I have created a small demo page with two editable ComboBox controls. The first one is filled with some ComboBoxItems, it's Text is set to 'Hello World !' which not exists as ComboBoxItem. The second is databound to some sample data (Products). There are three TextBlock controls below each ComboBox. The Text of the first TextBox is databound to the SelectedIndex of the ComboBox. The second to the SelectedItem using a custom function in the MainPage. The third to the Text property of the ComboBox.

As you expect you can now edit the text inside the ComboBox. The SelectedIndex is set to -1 once you type a custom text. The third TextBox which is databound to the Text is updated on a TextChanged of the Text, not only on lostfocus (like SelectedItem).

<StackPanel HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Width="300">
    
    <ComboBox x:Name="comboBox1"
              Header="ComboBox 1"
              IsEditable="True"
              Text="Hello World !"
              HorizontalAlignment="Stretch">
        <ComboBoxItem Content="A" />
        <ComboBoxItem Content="B" />
        <ComboBoxItem Content="C" />
        <ComboBoxItem Content="D" />
        <ComboBoxItem Content="E" />
    </ComboBox>
    <TextBlock Text="{x:Bind comboBox1.SelectedIndex, Mode=OneWay}" />
    <TextBlock Text="{x:Bind SelectedComboBoxItem(comboBox1.SelectedItem), Mode=OneWay}" />
    <TextBlock Text="{x:Bind comboBox1.Text, Mode=OneWay}" />

    <ComboBox x:Name="comboBox2"
              Margin="0,20,0,0"
              Header="ComboBox 2"
              IsEditable="True"
              ItemsSource="{x:Bind SampleData}"
              DisplayMemberPath="ProductName"
              HorizontalAlignment="Stretch"/>
    <TextBlock Text="{x:Bind comboBox2.SelectedIndex, Mode=OneWay}" />
    <TextBlock Text="{x:Bind SelectedProduct(comboBox2.SelectedItem), Mode=OneWay}" />
    <TextBlock Text="{x:Bind comboBox2.Text, Mode=OneWay}" />

</StackPanel>

In the MainPage class there is a SampleData property which contains some Product objects. It also contains the methods SelectedComboBoxItem() and SelectedProduct(). These methods are used for databinding the SelectedItem to the Text of the TextBlock. The SelectedComboBoxItem() shows the Content of the selected ComboBoxItem or the entered text. The SelectedProduct() shows the ProductName of the selected product or the entered text.

public sealed partial class MainPage : Page {

    internal List<Product> SampleData { get; } = new List<Product>() {
        new Product("Car", 20000),
        new Product("Bike", 800),
        new Product("Laptop", 400),
    };

    public MainPage() {
        this.InitializeComponent();
    }

    private string SelectedComboBoxItem(object selectedItem) {
        if (selectedItem is ComboBoxItem p) {
            return p.Content?.ToString();
        }
        return selectedItem?.ToString();
    }

    private string SelectedProduct(object selectedItem) {
        if (selectedItem is Product p) {
            return p.ProductName;
        }
        return selectedItem?.ToString();
    }
}

internal class Product {

    public string ProductName { get; set; }
    public decimal UnitPrice { get; set; }
    public Product(string productName, decimal unitPrice) {
        this.ProductName = productName;
        this.UnitPrice = unitPrice;
    }

}

TextBoxStyle

The ComboBox has also a new TextBoxStyle property. You can use it to define a custom style for the TextBox inside an editable ComboBox. I hoped that I could use it to remove the spell checking but unfortunately that doesn't work.

<ComboBox x:Name="comboBox1"
          Header="ComboBox 1"
          IsEditable="True"
          Text="Hello World !"
          HorizontalAlignment="Stretch">
    <ComboBox.TextBoxStyle>
        <Style TargetType="TextBox"
                BasedOn="{StaticResource ComboBoxTextBoxStyle}">
            <Setter Property="IsSpellCheckEnabled"
                    Value="False" />
        </Style>
    </ComboBox.TextBoxStyle>
    <ComboBoxItem Content="A" />
    <ComboBoxItem Content="B" />
    <ComboBoxItem Content="C" />
    <ComboBoxItem Content="D" />
    <ComboBoxItem Content="E" />
</ComboBox>

As you can see there is still a red squiggly line if you make a typo although I have set IsSpellCheckEnabled to False.

Closure

The IsEditable is a small but important new feature. WPF already had edtable ComboBoxes. In Windows Forms the ComboBox has a DropDownStyle which you can set to DropDown. Now you can have the same thing in UWP.

Fons

READ MORE

XAML new Description property for Input-Box controls

0 Comments
By Fons Sonnemans, 04-sep-2018

I'm in the process of learning the new Windows SDK Preview. Today's subject is the new Description property which is added to the TextBox, PasswordBox, RichEditBox, AutoSuggestBox and ComboBox input controls.

Demo

I have created a small demo page with all the input controls which have a Description. The Description is shown below the control in a gray color.

The XAML is very simple. The Description is of the type object. The PasswordBox in this example has a TextBlock with two Runs (one Bold) in it as the Description. It also supports DataBinding. The Description of the ComboBox is databound to the SelectedIndex.

<StackPanel HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Width="300"
            Spacing="8">
    <TextBox Header="TextBox"
                Text="Hello World!"
                Description="TextBox Description" />
    <PasswordBox Header="PasswordBox"
                    Password="secret">
        <PasswordBox.Description>
            <TextBlock>
        <Run Text="PasswordBox"
                FontWeight="Bold" />
        <Run Text="Description" />
            </TextBlock>
        </PasswordBox.Description>
    </PasswordBox>
    <RichEditBox Header="RichEditBox"
                    Description="RichEditBox Description" />
    <AutoSuggestBox Header="AutoSuggestBox"
                    Description="AutoSuggestBox Description" />
    <ComboBox Header="ComboBox"
                x:Name="comboBoxDemo"
                Description="{x:Bind comboBoxDemo.SelectedIndex, Mode=OneWay}"
                SelectedIndex="2"
                HorizontalAlignment="Stretch">
        <ComboBoxItem Content="A" />
        <ComboBoxItem Content="B" />
        <ComboBoxItem Content="C" />
        <ComboBoxItem Content="D" />
    </ComboBox>
</StackPanel>

Description color

You can easily change the color of the Description by defining a Brush Resource with the Key SystemControlDescriptionTextForegroundBrush. I added one to the StackPanel with the color Red.

<StackPanel HorizontalAlignment="Center"
            VerticalAlignment="Center"
            Width="300"
            Spacing="8">
    <StackPanel.Resources>
        <SolidColorBrush x:Key="SystemControlDescriptionTextForegroundBrush"
                         Color="Red" />
    </StackPanel.Resources>
    <TextBox Header="TextBox"
             Text="Hello World!"
             Description="TextBox Description" />

The Descriptions are now Red.

Closure

The Description is a small but nice new addition. Nothing you couldn't do yourself with a normal TextBlock but this is easier.

Fons

READ MORE

XAML MenuBar

1 Comments
By Fons Sonnemans, 27-aug-2018

I'm in the process of learning the new Windows SDK Preview. Today's subject is the new MenuBar control. You can now create menus with submenus in your UWP apps. Before you could use the Menu control from the Windows Community Toolkit.

Demo

I have created a small demo page which displays the following menu.

The XAML contains the new MenuBar control which contains two MenuBarItem elements. Each MenuBarItem contains MenuFlyoutItem, MenuFlyoutSeparator or MenuFlyoutSubItem elements. 

<Page x:Class="MenuBarDemo.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:MenuBarDemo"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      RequestedTheme="Light"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <MenuBar VerticalAlignment="Top">
            <MenuBarItem Title="File"
                         AccessKey="F">
                <MenuFlyoutItem Text="Open"
                                Icon="OpenFile"
                                Click="MenuFlyoutOpen_Click">
                    <MenuFlyoutItem.KeyboardAccelerators>
                        <KeyboardAccelerator Key="O"
                                             Modifiers="Control" />
                    </MenuFlyoutItem.KeyboardAccelerators>
                </MenuFlyoutItem>
                <MenuFlyoutSeparator />
                <MenuFlyoutItem Text="Save"
                                Icon="Save"
                                Command="{x:Bind SaveCommand}">
                    <MenuFlyoutItem.KeyboardAccelerators>
                        <KeyboardAccelerator Key="S"
                                             Modifiers="Control" />
                    </MenuFlyoutItem.KeyboardAccelerators>
                </MenuFlyoutItem>
                <MenuFlyoutSubItem Text="Demo">
                    <MenuFlyoutItem Text="A"
                                    Command="{x:Bind DemoCommand}"
                                    CommandParameter="{Binding Text, 
                                        RelativeSource={RelativeSource Self}, 
                                        Mode=OneTime}" />
                    <MenuFlyoutItem Text="B"
                                    Command="{x:Bind DemoCommand}"
                                    CommandParameter="{Binding Text, 
                                        RelativeSource={RelativeSource Self}, 
                                        Mode=OneTime}" />
                    <MenuFlyoutItem Text="C"
                                    Command="{x:Bind DemoCommand}"
                                    CommandParameter="{Binding Text, 
                                        RelativeSource={RelativeSource Self}, 
                                        Mode=OneTime}" />
                </MenuFlyoutSubItem>
            </MenuBarItem>
            <MenuBarItem Title="Help"
                         AccessKey="H">
                <MenuFlyoutItem Text="About"
                                Click="MenuFlyoutItemAbout_Click" />
            </MenuBarItem>
        </MenuBar>
    </Grid>
</Page>

The C# code with the Click handlers and the Commands looks like this.

public sealed partial class MainPage : Page {
    public ICommand SaveCommand { get; }
    public ICommand DemoCommand { get; }

    public MainPage() {
        this.InitializeComponent();
        this.SaveCommand = new RelayCommand(OnSave);
        this.DemoCommand = new RelayCommand<string>(OnDemo);
    }

    private async void OnDemo(string text) {
        await new MessageDialog($"Demo {text}").ShowAsync();
    }

    private async void OnSave() {
        await new MessageDialog("Save").ShowAsync();
    }

    private async void MenuFlyoutOpen_Click(object sender, RoutedEventArgs e) {
        await new MessageDialog("Open").ShowAsync();
    }

    private async void MenuFlyoutItemAbout_Click(object sender, RoutedEventArgs e) {
        await new MessageDialog("About").ShowAsync();
    }
}

AccessKey and KeyboardAccelerators

The MenuBarItem have an AccessKey assigned. So if you press the Alt key on your keyboard you get the following output. Alt+F will open the File menu, Alt+H will open the Help menu.

The Open and Save MenuFlyoutItem have a KeyboardAccelerator. Ctrl+O will execute the Open menu, Ctrl+S will execute the Save menu.

Closure

The MenuBar is a great new addition. It will help me writing nice LOB applications. You can download this sample project from this GitHub repository.

Fons

READ MORE

XAML Control.CornerRadius

0 Comments
By Fons Sonnemans, 22-aug-2018

I'm in the process of learning the new Windows SDK Preview. Yesterday I wrote a blog about the new AppBarElementContainer. Today's subject is the new CornerRadius property of the Control class. Until now most input controls where rectangular. Now they can have rounded corners.

Demo

I have created a small demo page in which I placed a few input controls in a StackPanel. For all controls I have set the CornerRadius to 8.

<Page x:Class="App2.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App2"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid>
        <StackPanel HorizontalAlignment="Center"
                    VerticalAlignment="Center"
                    Spacing="8">
            <Button Content="Hello"
                    HorizontalAlignment="Stretch"
                    CornerRadius="8"
                    FontSize="20"
                    Margin="0,0,0,0"
                    VerticalAlignment="Center" />
            <TextBox Text="World"
                     CornerRadius="8" />
            <PasswordBox CornerRadius="8" />
            <ComboBox SelectedIndex="0"
                      HorizontalAlignment="Stretch"
                      CornerRadius="8">
                <ComboBoxItem Content="A" />
                <ComboBoxItem Content="B" />
                <ComboBoxItem Content="C" />
            </ComboBox>
            <TimePicker CornerRadius="8" />
        </StackPanel>
    </Grid>
</Page>

this results in the following output. The Button, TextBox, PasswordBox and ComboBox have rounded corners. Unfortunately the TimePicker does not. I hope it will be fixed before it released.

The focus rectangle of a Button is also still rectangular. I expect that will stay like this.

Closure

The CornerRadius is a nice new feature. I will maybe use it a one of my games. Probably not in a LOB app.

Fons

READ MORE

XAML AppBarElementContainer

0 Comments
By Fons Sonnemans, 21-aug-2018

I have been playing with the new Windows Insider Preview SDK build 17733. It contains a new control named AppBarElementContainer. This control allows you to add other controls then the AppBarButton, AppBarSeparator and AppBarToggleButton to a CommandBar or the "depricated" AppBar.

Demo

AppBarElementContainer is a container control so you can place any control (which fit inside the limited space) into it. In the next example I used for this demo a ComboBox and a Slider.

<Page x:Class="App1.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:App1"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <CommandBar VerticalAlignment="Top">
            <CommandBar.PrimaryCommands>
                <AppBarButton Icon="Save"
                              Label="Save" />
                <AppBarElementContainer>
                    <ComboBox Width="200"
                              Margin="0,4,0,0"
                              SelectedIndex="0">
                        <ComboBoxItem Content="A" />
                        <ComboBoxItem Content="B" />
                        <ComboBoxItem Content="C" />
                    </ComboBox>
                </AppBarElementContainer>
                <AppBarElementContainer>
                    <Slider Width="200"
                            Margin="4" />
                </AppBarElementContainer>
                <AppBarButton Icon="Delete"
                              Label="Delete"
                              LabelPosition="Collapsed" />
            </CommandBar.PrimaryCommands>
            <CommandBar.SecondaryCommands>
                <AppBarButton Icon="Undo"
                              Label="Undo" />
                <AppBarButton Icon="Redo"
                              Label="Redo" />
            </CommandBar.SecondaryCommands>
            <CommandBar.Content>
                <TextBlock Text="Hello World"
                           Margin="8" />
            </CommandBar.Content>
        </CommandBar>
    </Grid>
</Page>

The app looks like this

When there is not enough space to show all primary commands they are automatically moved to the secondary commands. This also works for the AppBarElementContainer. If you want to add multiple controls to a CommandBar, don't put them in a horizontal StackPanel inside a AppBarElementContainer. Place each control in it's own AppBarElementContainer. Just like I did.

Closure

I really like the new AppBarElementContainer. I will use it a lot in my new apps running on Windows 10 (1809).

Fons

READ MORE

All postings/content on this blog are provided "AS IS" with no warranties, and confer no rights. All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors. The content on this site is licensed under a Creative Commons Attribution By license.