Skip to content

Debugging

Mahmoud Ali edited this page Apr 4, 2021 · 3 revisions

Sometimes you try to find an element on the screen and for some reason it is not there. In these cases, it is important to know what was rendered to the screen, to better understand what might be happening.

Since nothing actually gets drawn because we are not running on any specific platform, the best we can do at the moment is show you what controls were added to the Page, with all its properties.

The Screen object has a useful method for that called Debug. Anytime you call the Debug method, a tree will be rendered to the desired output (Console.Out by default) showing all the page hierarchy with its relevant properties. The Debug also returns the same string that was rendered, so you can inspect it or store it in a variable.
You can call Debug any time so you can see the page before or after you interact with it.

Here's an example:

We have this simple page:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:Xamarin.Forms.TestingLibrary.SampleApp.Converters"
             xmlns:viewModels="clr-namespace:Xamarin.Forms.TestingLibrary.SampleApp.ViewModels"
             x:DataType="viewModels:Example1PageViewModel"
             x:Class="Xamarin.Forms.TestingLibrary.SampleApp.Pages.Example1Page">
    <ContentPage.Resources>
        <ResourceDictionary>
            <local:IsNullOrEmptyConverter x:Key="IsNullOrEmptyConverter" />
        </ResourceDictionary>
    </ContentPage.Resources>
    <StackLayout>
        <Label Text="Login"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="CenterAndExpand"
               IsVisible="False">
            <Label.Triggers>
                <DataTrigger Binding="{Binding UserName, Converter={StaticResource IsNullOrEmptyConverter}}"
                             Value="True"
                             TargetType="Label">
                    <Setter Property="IsVisible" Value="True" />
                </DataTrigger>
            </Label.Triggers>
        </Label>

        <Label IsVisible="False"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="CenterAndExpand">
            <Label.Triggers>
                <DataTrigger Binding="{Binding UserName, Converter={StaticResource IsNullOrEmptyConverter}}"
                             Value="False"
                             TargetType="Label">
                    <Setter Property="IsVisible" Value="True" />
                </DataTrigger>
            </Label.Triggers>
            <Label.FormattedText>
                <FormattedString>
                    <Span Text="Welcome back, " />
                    <Span Text="{Binding UserName}" />
                    <Span Text="!" />
                </FormattedString>
            </Label.FormattedText>
        </Label>
    </StackLayout>
</ContentPage>

By setting the screen with some information:

var viewModel = new Example1PageViewModel {UserName = "Marvin"};
var screen = _renderer.Render<Example1Page>();
screen.ProvideBingingContext(viewModel);

screen.Debug();

We can call the Debug method, to see only the rendered elements in the debug tree:

Example1Page
└── StackLayout
    └── Label
        ├── IsVisible: True
        ├── VerticalOptions: CenterAndExpand
        ├── HorizontalOptions: CenterAndExpand
        ├── Bound: False
        ├── FormattedText: Welcome back, Marvin!
        └── Text: <null>

As you can see, the debug tree correctly showed only what is visible in the page, all the other elements that were not visible because some property or trigger were not set are not rendered. Exactly as you would see if you ran the app in any platform.

You can customize the Debug behaviour by setting its options, as described here.

Clone this wiki locally