Thursday, June 16, 2016

How To Debug XAML Design Views

When I work on a XAML view, I'll switch between the run-time view in the app, the XAML view, or the Design view, depending on what I'm trying to do at the moment. As I mentioned in my previous post, I'm a big fan of using the XAML Design views with sample data.

On occasion, something goes into the ditch, and I can't get the Design view to work. Since I lean towards the x:Bind syntax, a broken view might revert to showing the data bound property name instead of the sample data I've curated for it. Depending on how the app is configured, it might run great at run-time, but the design-time path is broken.

Visual Studio 2015 has a great debugger, and these steps show how to attach it to the Design view and uncover hidden exceptions that are not surfaced in the Design view.

How to Attach the Debugger to XAML Design Views

Step 1: Close all open files in Visual Studio 2015 and Blend.

Make sure both editors are launched and have the solution loaded; just make make sure all the files are closed. If Blend isn't launched yet, right-click the XAML file in the Solution Explorer, and select "Design In Blend".

Step 2: Open the code-behind file of the view and set a break point in the constructor. Let's ignore the flaw in the magic string that reaches into the resource dictionary in the following example for now and pretend it's a more complex error.

Pro-Tip: Select "x86" in the Solution Platforms drop down (in Visual Studio and Blend!) because this won't work when set to "Arm".



Step 3:  Attach the debugger to Blend

In Visual Studio 2015, select Debug > Attach To Process...


In the "Attach to Process" panel, verify the "Attach to" field is set to managed code.

Next, select "XDesProc.exe" at or near the bottom of the list. You should see two items with the same name, so hover over them and select the item with "Blend" in the tooltip. The other item is for Visual Studio 2015.



Step 4: Open the XAML design view in Blend

This action instantiates the view code-behind and results in the break point halting execution of your Design view experience.

Step 5: Observe the break point hit, and step through your code



From here you can observe the execution path taken by the Design view and hopefully deduce the cause for the Design view issue. Typically, you'll see the issue right away and realize your View or View Model was violating an obvious pattern. In my contrived case, I misspelled the key name of the resource dictionary item.

Attaching the Visual Studio 2015 debugger to Blend isn't always stable. There's lot of moving parts, so if you run into issues, you might restart both editors, clean and recompile, verify the Solution Platform configuration and other acts of superstition to jiggle your particular issue loose.

Tuesday, June 14, 2016

UWP Design Preview with x:Bind

When I work with XAML, I really enjoy using the full toolset. Blend offers a great complimentary toolset to Visual Studio 2015 and the Design tab lets me preview the content as I build it. As I understand it, the Design tab in VS 2015 runs the same version of the preview as Blend.

The new x:Bind syntax in XAML for Windows 10 UWP provides a compile type check; improving my confidence that I'm headed down the right path as I build the view. I was surprised to learn that x:Bind constrains the output of the sample data in the Design tab of Blend or Visual Studio 2015.

By default, the Design tab will simply show the property name of an x:Bind statement. That's better than nothing, but still a large constraint. I'd like to see my specific sample data.

I couldn't solve this problem with timer (a long running joke at my shop), but I did figure out a way. The following example shows how to display your custom sample data in the Design tab when data binding with the new x:Bind syntax.

View Model

Pretty simple, nothing fancy. The run-time data is not implemented, this is just about the design time experience:

using Windows.ApplicationModel;

namespace MyApp
{
    public class MainPageViewModel
    {
        public MainPageViewModel()
        {
            if (DesignMode.DesignModeEnabled)
            {
                Name = "Alice";
            }
        }

        public string Name { get; set; }
    }
}

View Code-Behind

One of the common tricks in using x:Bind is to include a "ViewModel" property in order to get benefits of the MVVM separation. x:Bind uses the code-behind file instead of a DataContext property to fulfill databinding requests. In addition to compile-time checking; the app avoids run-time reflection, which boosts performance over the standard Binding syntax.

using Windows.UI.Xaml.Controls;

namespace MyApp
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            ViewModel = new MainPageViewModel();
        }

        public MainPageViewModel ViewModel { get; set; }
    }
}

Standard View: XAML 

This view is uses the x:Bind syntax to display the property "Name" hanging off the ViewModel object. If I make a mistake in the x:Bind statement, the compiler will yell at me.

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

    <Grid>
        <TextBlock Text="{x:Bind ViewModel.Name}" /> 
    </Grid>
    
</Page>

Standard View: Design

Some say "standard", I say "broken". This design view doesn't show my sample data, but shows the property name instead.


Sample Data View: XAML 

It turns out that by specifying the design-time data context (which is ignored at run-time), the Design tab can regain access to the sample data.


<Page x:Class="MyApp.MainPage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:local="using:MyApp"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      mc:Ignorable="d"
      d:DataContext="{d:DesignInstance Type=local:MainPage,IsDesignTimeCreatable=True}">

    <Grid>
        <TextBlock Text="{x:Bind ViewModel.Name}" /> 
    </Grid>


</Page>

Sample Data View: Design



Summary

By adding the d:DataContext attribute to your XAML view, you can instruct the design time to create another instance of your code-behind file, which happens to have a ViewModel property with your expected sample data. It's a little weird, albeit hacky, to mix the DataContext and code-behind instances like this but it makes the sample data available.

Note, this example says nothing about the View Model is applied at run-time, INotifyPropertyChanged, and other ceremonial aspects of XAML and MVVM, I'm just demonstrating the sample data in the Design tab with x:Bind in this post.