Skip to content
A Xamarin.Forms Inspector
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Assets/Images adding images Aug 22, 2017
Desktop adding scrollbar to connection manager and forcing angular version in… Sep 21, 2017
Mobile Adding uisleuth projects Aug 17, 2017
Nuget Adding uisleuth projects Aug 17, 2017
Server Adding uisleuth projects Aug 17, 2017
.gitattributes Adding uisleuth projects Aug 17, 2017
.gitignore
LICENSE Initial commit Aug 16, 2017
README.md

README.md

UI Sleuth

A Xamarin.Forms Inspector

Download Desktop Client · Download NuGet Package · Installation Guide · Wiki


What is UI Sleuth?

UI Sleuth is a Xamarin.Forms debugging tool. If you’ve ever made a web site, it’s similar to Microsoft’s F12 tools or Chrome Developer Tools. You can use it to efficiently track down layout issues, prototype a new design, and remotely control a device.

Screenshots


Attached to Android tablet.


Inspecting a ViewModel

Overview

UI Sleuth is composed of two components: the desktop client and the design server. The desktop client communicates with your mobile app via WebSockets and a simple JSON protocol. The .NET library that you reference in your Xamarin.Forms application is a WebSocket server and workflow engine.

The workflow engine is implemented using a BlockingCollection that dispatches incoming messages to listeners, called Reactions. Once a request has been received, its serialized into the appropriate .NET type. Each request type is associated with a reaction. When the corresponding reaction is determined, its instantiated and invoked. The implementing reaction can read the incoming message, perform some behavior, and return a response to the client.

As an example, the following code is used to respond to a screenshot request from the desktop client.

1) Define the request and response types (server code)

namespace UISleuth.Messages
{
    internal class ScreenShotRequest : Request {}

    internal class ScreenShotResponse : Response
    {
        public byte[] Capture { get; set; }
    }
}

2) Create a custom reaction class (server code)

    internal class ScreenShotReaction : Reaction
    {
        protected override void OnExecute(UIMessageContext ctx)
        {
            var request = ctx.Get<ScreenShotRequest>();
            if (request == null) return;

            var screenshot = InspectorContainer.Current.Resolve<IScreenShot>();
            byte[] capture = null;

            Thread.Invoke(() =>
            {
                capture = screenshot.Capture();
            });

            ctx.SetResponse<ScreenShotResponse>(r =>
            {
                r.Capture = capture;
                r.Suggest<GetVisualTreeRequest>();
            });
        }
    }

3) Associate the request type to the reaction (server code)

Reaction.Register<ScreenShotRequest, ScreenShotReaction>();

4) Request a screenshot via WebSocket (client code)

websocket.send("{action: 'ScreenShotRequest'}");

The action property above matches the C# type name of ScreenShotRequest. Additional parameters can be present in this message. Utility methods exist to easily deserialize these messages into the appropriate .NET objects.

* Request types are optional. You may chose to send an OkResponse

Why WebSockets?

When this project started, Xamarin.Forms was a UI toolkit for iOS, Android, and Windows Phone apps only. I needed a simple, out of process way to communicate with external emulators and devices. WebSockets just made sense.

Now that we're seeing Xamarin.Forms target WPF, GTK#, and macOS a whole new level of possibilites for UI Sleuth are emerging. Let's imagine your new client wants to communicate with your Xamarin.Forms app via IPC instead of WebSockets for out-of-process communication. That's great; start by extending the InspectorSocket type and register it with the DI service.

Documentation

This project site is a work in progress. You can find all the documentation on the project's Wiki.

@mykldavis

You can’t perform that action at this time.