In my previous article, I’ve explained how to use Roslyn to implement a feature available in Resharper that allows you to easily change the modifier(s) of a property.

Today, we’ll see how we can implement another great feature: we’ll allow the user to easily replace a type by “var” in the declaration of a variable:

image

To do this, we’ll use a diagnostic analyser that will analyse our syntax tree:

public override void Initialize(AnalysisContext context)
{
    context.RegisterSyntaxTreeAction(DetectInitializedVariableDeclaration);
}

The method will inspect the syntax tree to detect all the element of type VariableDeclarationSyntax.  For each element, we’ll retrieve the EqualsValueClauseSyntax object and, if there is one (meaning the variable has been initialized), we’ll add our diagnostic on the type element:

private async static void DetectInitializedVariableDeclaration(SyntaxTreeAnalysisContext context)
{
    var root = await context.Tree.GetRootAsync();
    var variableDeclarationSyntaxElements = root.DescendantNodesAndSelf().OfType<VariableDeclarationSyntax>();

    if (variableDeclarationSyntaxElements.Any())
    {
        for (int i = 0; i < variableDeclarationSyntaxElements.Count(); i++)
        {
            var variableDeclaration = variableDeclarationSyntaxElements.ElementAt(i);

            var equalsValueClauseSyntaxElements = variableDeclaration.DescendantNodesAndSelf().OfType<EqualsValueClauseSyntax>();
            if (equalsValueClauseSyntaxElements.Any())
            {
                foreach (var equalsValueClause in equalsValueClauseSyntaxElements)
                {
                    var nodeType = variableDeclaration.DescendantNodesAndSelf().OfType<PredefinedTypeSyntax>().FirstOrDefault();
                    if (nodeType != null && !nodeType.IsVar)
                    {
                        // Add "contextual" menu to use 'var' instead of the real type
                        var diagnostic = Diagnostic.Create(UseVarRule, nodeType.GetLocation());

                        context.ReportDiagnostic(diagnostic);
                    }
                }
            }
        }
    }
}

The code fix provider associated is pretty simple:

public sealed override async Task ComputeFixesAsync(CodeFixContext context)
{
    var diagnostic = context.Diagnostics.First();

    var diagnosticSpan = diagnostic.Location.SourceSpan;

    var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

    var predefinedType = root.FindNode(diagnostic.Location.SourceSpan) as PredefinedTypeSyntax;
    if (predefinedType != null)
    {
        var variableDeclarationSyntaxElement = predefinedType.Parent as VariableDeclarationSyntax;
        if (variableDeclarationSyntaxElement != null)
        {
            context.RegisterFix(CodeAction.Create("Use 'var'", c => UseVarKeywordAsync(context.Document, variableDeclarationSyntaxElement, c)), diagnostic);
        }
    }
}

The method “UseVarKeyword” will perform all the magic here: it will create a copy of our element by adding the previous trivia and changing the type (using ‘var’ instead of the actual type).

private static async Task<Document> ReplaceNodeInDocumentAsync(
    Document document,
    SyntaxNode oldNode,
    SyntaxNode newNode,
    CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken);
    var newRoot = root.ReplaceNode(oldNode, newNode);

    return document.WithSyntaxRoot(newRoot);
}

private static async Task<Document> UseVarKeywordAsync(
    Document document,
    VariableDeclarationSyntax variableDeclarationSyntaxElement,
    CancellationToken cancellationToken)
{
    // var is not a real keyword in C# so create an identifier named 'var': http://stackoverflow.com/questions/14777133/declaring-var-variables-with-roslyn-sept-2012-ctp
    var newVariableDeclarationSyntaxElement = variableDeclarationSyntaxElement.WithType(SyntaxFactory.IdentifierName("var "));
    newVariableDeclarationSyntaxElement = newVariableDeclarationSyntaxElement.WithLeadingTrivia(variableDeclarationSyntaxElement.GetLeadingTrivia());

    return await ReplaceNodeInDocumentAsync(document, variableDeclarationSyntaxElement, newVariableDeclarationSyntaxElement, cancellationToken);
}

Note that ‘var’ is not a real C# keyword so we’ll need to create a “custom” identifier named ‘var’.

Once executed, the extension allows us to have the following:

image

image

As you can see, using Roslyn, it’s really easy to add your custom rules to Visual Studio!

 

Happy coding!

One of the feature that I like in Resharper is the one that allow you to easily change the modifiers of any properties:

image

Thanks to Visual Studio 2015 and Roslyn, it’s now possible to provide the same kind of experience using a custom extension.

To implement this feature, we need to create a diagnostic analyser and a code fix provider. So let’s take a look at the diagnostic analyser:

public class CSharpEssentialsAnalyzer : DiagnosticAnalyzer
{
    public const string DiagnosticId = "CSharpEssentials";

    #region Change Modifier

    internal const string ChangeModifierRuleTitle = "Change modifier";
    internal const string ChangeModifierRuleMessageFormat = "Change modifier for '{0}'";
    internal const string ChangeModifierRuleCategory = "Refactoring";

    internal static DiagnosticDescriptor ChangePropertyModifierRule = new DiagnosticDescriptor(
        DiagnosticId,
        ChangeModifierRuleTitle,
        ChangeModifierRuleMessageFormat,
        ChangeModifierRuleCategory,
        DiagnosticSeverity.Info,
        isEnabledByDefault: true);

    #endregion

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
    {
        get
        {
            return ImmutableArray.Create(ChangePropertyModifierRule);
        }
    }

    public override void Initialize(AnalysisContext context)
    {
        context.RegisterSymbolAction(AnalyzePropertySymbol, SymbolKind.Property);
    }

    private static void AnalyzePropertySymbol(SymbolAnalysisContext context)
    {
        var propertySymbol = context.Symbol as IPropertySymbol;
        if (propertySymbol != null)
        {
            // Add "contextual" menu to change property modifiers.
            var diagnostic = Diagnostic.Create(ChangePropertyModifierRule, propertySymbol.Locations[0], propertySymbol.Name);

            context.ReportDiagnostic(diagnostic);
        }
    }
}

The code is simple to understand: on the Initiliaze method, we register a action that will be called for each property of the source code (of the current document). On that action, we check if we are really on a property (this should always be the case but it’s still a good thing to check) and we add a diagnostic at the property’s location. A diagnostic is the way to add an indicator on Visual Studio’s margin, telling “hey! there is something to check here”. This can be an error, a warning or an information.

Running the previous code, we can see the indicator:

image

By changing the severity of the rule that’s broken, we can change the way the indicator is shown. Here is the result if we specify a severity of kind “Error” (the property’s identifier is underlined in red)

image

Now that the indicator (the yellow light bulb) is show, we need to indicate to the user the different kind of fixes he can do. So we have to implement a Code fix provider (by inherited from the class CodeFixProvider):

public class CSharpEssentialsCodeFixProvider : CodeFixProvider
{
    private SyntaxToken _whitespaceToken =
        SyntaxFactory.Token(SyntaxTriviaList.Create(SyntaxFactory.Space), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty);

    public sealed override ImmutableArray<string> GetFixableDiagnosticIds()
    {
        return ImmutableArray.Create(CSharpEssentialsAnalyzer.DiagnosticId);
    }

    public sealed override FixAllProvider GetFixAllProvider()
    {
        return WellKnownFixAllProviders.BatchFixer;
    }

    public sealed override async Task ComputeFixesAsync(CodeFixContext context)
    {
        var diagnostic = context.Diagnostics.First();
        var diagnosticSpan = diagnostic.Location.SourceSpan;

        var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

        var property = root.FindNode(diagnosticSpan) as PropertyDeclarationSyntax;
        if (property != null)
        {
            if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.PublicKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To private", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PrivateKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To protected", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.ProtectedKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To internal", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.InternalKeyword, c)),
                    diagnostic);
            }
            else if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.PrivateKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To public", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PublicKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To protected", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.ProtectedKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To internal", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.InternalKeyword, c)),
                    diagnostic);
            }
            else if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.ProtectedKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To public", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PublicKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To private", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PrivateKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To internal", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.InternalKeyword, c)),
                    diagnostic);
            }
            else if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.InternalKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To public", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PublicKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To private", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PrivateKeyword, c)),
                    diagnostic);

                context.RegisterFix(
                    CodeAction.Create("To protected", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.ProtectedKeyword, c)),
                    diagnostic);
            }

            if (!property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.VirtualKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To virtual", c => AddPropertyModifierAsync(context.Document, property, SyntaxKind.VirtualKeyword, c)),
                    diagnostic);
            }
            else if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.VirtualKeyword))
            {
                context.RegisterFix(
                    CodeAction.Create("To non virtual", c => RemovePropertyModifierAsync(context.Document, property, SyntaxKind.VirtualKeyword, c)),
                    diagnostic);
            }
        }
    }

    private async Task<Document> AddPropertyModifierAsync(
        Document document,
        PropertyDeclarationSyntax property,
        SyntaxKind propertyModifier,
        CancellationToken cancellationToken)
    {
        //var semanticModel = await document.GetSemanticModelAsync(cancellationToken);
        //var propertySymbol = semanticModel.GetDeclaredSymbol(property, cancellationToken);

        var newProperty = property.AddModifiers(SyntaxFactory.Token(propertyModifier), _whitespaceToken);

        return await ReplacePropertyInDocumentAsync(document, property, newProperty, cancellationToken);
    }

    private async Task<Document> RemovePropertyModifierAsync(
        Document document,
        PropertyDeclarationSyntax property,
        SyntaxKind propertyModifier,
        CancellationToken cancellationToken)
    {
        var syntaxTokenList = new SyntaxTokenList();

        var existingModifiersWithoutSpecifiedModifier = property.Modifiers.Where(m => m.CSharpKind() != propertyModifier);
        foreach (var item in existingModifiersWithoutSpecifiedModifier)
        {
            syntaxTokenList = syntaxTokenList.Add(item);
        }

        var newProperty = SyntaxFactory.PropertyDeclaration(new SyntaxList<AttributeListSyntax>(), syntaxTokenList, property.Type, null, property.Identifier, property.AccessorList);

        return await ReplacePropertyInDocumentAsync(document, property, newProperty, cancellationToken);
    }

    private async Task<Document> ReplacePropertyModifierAsync(
        Document document,
        PropertyDeclarationSyntax property,
        SyntaxKind propertyModifier,
        CancellationToken cancellationToken)
    {
        var previousWhiteSpacesToken = SyntaxFactory.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty);

        var newProperty = property.WithModifiers(SyntaxTokenList.Create(previousWhiteSpacesToken)
            .Add(SyntaxFactory.Token(propertyModifier))
            .Add(_whitespaceToken));

        if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.VirtualKeyword))
        {
            newProperty = newProperty.AddModifiers(SyntaxFactory.Token(SyntaxKind.VirtualKeyword), _whitespaceToken);
        }

        return await ReplacePropertyInDocumentAsync(document, property, newProperty, cancellationToken);
    }

    private static async Task<Document> ReplacePropertyInDocumentAsync(
        Document document,
        PropertyDeclarationSyntax property,
        PropertyDeclarationSyntax newProperty,
        CancellationToken cancellationToken)
    {
        var root = await document.GetSyntaxRootAsync(cancellationToken);
        var newRoot = root.ReplaceNode(property, new[] { newProperty });

        return document.WithSyntaxRoot(newRoot);
    }
}

This class might be a bit more complicated but, in fact, it’s pretty simple. The method ComputeFixesAsync is used to show to the user the available fixes that he can used. To display this fixes, we need to get the different diagnostics of the location we are and show the fixes available for the dedicated diagnostics.

In our case, we want to change the modifiers of the property we first need to check the current modifier and show the fixes:

if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.PublicKeyword))
{
    context.RegisterFix(
        CodeAction.Create("To private", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.PrivateKeyword, c)),
        diagnostic);

    context.RegisterFix(
        CodeAction.Create("To protected", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.ProtectedKeyword, c)),
        diagnostic);

    context.RegisterFix(
        CodeAction.Create("To internal", c => ReplacePropertyModifierAsync(context.Document, property, SyntaxKind.InternalKeyword, c)),
        diagnostic);
}

In a code fix provider class, we have access to the current document and we’ll use it to show the preview of what will be the result’s code if the user select a dedicated fix. We can’t just update the current document so we need to create a copy of the document and edit it on the fly:

private async Task<Document> ReplacePropertyModifierAsync(
    Document document,
    PropertyDeclarationSyntax property,
    SyntaxKind propertyModifier,
    CancellationToken cancellationToken)
{
    var previousWhiteSpacesToken = SyntaxFactory.Token(property.GetLeadingTrivia(), SyntaxKind.StringLiteralToken, SyntaxTriviaList.Empty);

    var newProperty = property.WithModifiers(SyntaxTokenList.Create(previousWhiteSpacesToken)
        .Add(SyntaxFactory.Token(propertyModifier))
        .Add(_whitespaceToken));

    if (property.Modifiers.Any(m => m.CSharpKind() == SyntaxKind.VirtualKeyword))
    {
        newProperty = newProperty.AddModifiers(SyntaxFactory.Token(SyntaxKind.VirtualKeyword), _whitespaceToken);
    }

    return await ReplacePropertyInDocumentAsync(document, property, newProperty, cancellationToken);
}

private static async Task<Document> ReplacePropertyInDocumentAsync(
    Document document,
    PropertyDeclarationSyntax property,
    PropertyDeclarationSyntax newProperty,
    CancellationToken cancellationToken)
{
    var root = await document.GetSyntaxRootAsync(cancellationToken);
    var newRoot = root.ReplaceNode(property, new[] { newProperty });

    return document.WithSyntaxRoot(newRoot);
}

As you can see, changing a property’s modifier is simple: we copy the property and add the specified modifier (if the “virtual” modifier has been already added, we copy it again). Note that we also add a whitespace after the modifier so the syntax will be respected.

Once executed, the code will allow to display the following fixes:

image

image

When user put its mouse over a fix, we can see a preview of the fix (the red lines consists of the code that will be removed and the green lines are the code that will be added):

image

image

Of course, the “Preview changes” feature works here too:

image

The good point is that we just modified the modifiers without changing the accessors. So if you have dedicated code in the get/set, it will be persisted:

image

 

As you can see, Roslyn give you a powerful object model to manipulate your code. You will now be able to create powerful extensions in a simple manner!

 

Happy coding!

For an addin I’m workin on, I wanted to present a window to the user but only when Visual Studio is starting a debug session.

For that, I’ve found you can use the IVsDebuggerEvents interface which provides notifications when debugger changes mode.

On the class that need to be notified of the changes, get the current debugger and register for debug events:

uint _debugEventsCookie = VSConstants.VSCOOKIE_NIL;

_debugger = (IVsDebugger)this.GetService(typeof(IVsDebugger));
ErrorHandler.ThrowOnFailure(_debugger.AdviseDebuggerEvents(this, out _debugEventsCookie));

Once this is done, the method IVsDebuggerEvents.OnModeChange will be called so you’ll be able to know when the debugger changes mode:

int IVsDebuggerEvents.OnModeChange(DBGMODE dbgmodeNew)
{
    switch (dbgmodeNew)
    {
        case DBGMODE.DBGMODE_Run:
            // Start Debug Session
            break;
        case DBGMODE.DBGMODE_Break:
            // Break Debug Session
            break;
        case DBGMODE.DBGMODE_Design:
            // Stop Debug Session
            break;
    }

    return VSConstants.S_OK;
}

Of course, don’t forget to perform some cleanup when you’ve finished:

protected override void Dispose(bool disposing)
{
    if (_debugEventsCookie != VSConstants.VSCOOKIE_NIL && _debugger != null)
    {
        ErrorHandler.CallWithCOMConvention(() => _debugger.UnadviseDebuggerEvents(_debugEventsCookie));

        _debugEventsCookie = VSConstants.VSCOOKIE_NIL;
    }

    base.Dispose(disposing);
}

That’s all (so simple isn’t it ? ;-)

 

Happy coding!

I like to think that I’m open minded enough to look at a lot of things. Recently, I’ve started to look at Xamarin not to start developing apps on Android but just to be able to know the product and I have to say that it’s very interesting. I’ll try to make more posts on it but, for now, let’s take a look that the big picture of it!

 

What is Xamarin ?

 

 Xamarin is a set of tools developers can use to delivers high performance compiled code with full access to all the native APIs so you can create native apps with device-specific experiences. Anything you can do in Objective-C or Java, you can do in C# with Xamarin.

The other good point is that even if you can use Xamarin Studio to develop your app, you can also use Visual Studio and all the other tools you already use for any C# development. This include Team Foundation Server (for the source control) but also plugins like Resharper, GhostDoc, etc.

Finally, to let you share code easily across iOS, Android and Windows Phone, you can also use the Portable Class Library (PCL) to create a core component that will be available on all the platforms (only the GUI part will be specific). The following article give your more details on how to work with the PCL and Xamarin Studio or Visual Studio (if you are already using the PCL on Visual Studio, you’ll see that there are no big differences!).

 

How does it work ?

Xamarin offers 2 mains products: Xamarin.iOS (MonoTouch.dll) and Xamarin.Android (Mono.Android.dll). Both of them are developed on top of Mono, the open source version of the .NET Framework. For those who have been on the .NET community for a long time, you may remembered that Mono project has been initiate by Miguel De Icaza, the co-founder and current CTO of… Xamarin :)

On iOS, a dedicated compiler (AOT: Ahead Of Time) compiles applications written on C# directly to native ARM code.

For Android, the process is similar to the .NET compilation and execution: the source code is compiled to an Intermediate Language (IL) and, when the code is executed on the device, a second compilation (performed Just-In-Time, JIT) compile the IL to native code. This makes sense because Android applications are used to be developed in Java, which has an internal architecture similar to the .NET architecture.

In both case, you don’t have to worry about the memory management, resources allocation, etc.: all is managed, for you, by the runtime delivered by Xamarin.

Once compiled, the Android applications are packaged in a file with the .apk extension. Like XAP files, these files are only ZIP files that contains:

  • The Android manifest file, on binary format (more on that later)
  • The application code (compiled into the file classes.dex)
  • The differents assets included in the package
  • The differents resources (layouts, drawable)
  • The native libraries containing the Mono runtime.

This last point is important. Indeed, an Android application must be deployed with the native libraries for the desired architecture (armeabi, armeabi-v7a, x86). Be careful that your application won’t be able to run on a particular plateform until the dedicated runtime libraries are deployed on it:

image image

Finally, the Android application also contains the Android Callable Wrappers (ACW), which allows you to call managed code from the Android runtime. The full definition of the Android Callable Wrappers can be found online but, basically, this is similar to the Runtime Callable Wrappers (RCW): a proxy object that allows Java (or COM) to allow .NET code, without having to handle the difference of type between the two worlds. On the other side, the Managed Callable Wrappers (MCW) are bridges allowing .NET code to invoke Android code (so this is the opposite of Android Callable Wrappers). Managed callable wrappers are responsible for converting between managed and Android types and invoking the underlying Android platform methods.

 

What tools are available ?

Xamarin has its own IDE, Xamarin Studio, that looks like a lot to Visual Studio (well, to be honest, it’s more like the first version of SharpDevelop but at least, it’s working):

image

But Xamarin Studio can only be used to develop Android applications, not iOS apps:

image

Fortunately, for the .NET developers we are, it’s also possible to use Visual Studio to develop iOS and Andoid applications!

image

Xamarin also come with a lot of emulators that are available through Xamarin Studio and Visual Studio:

image image

There is also a very nice device manager that allow you to manage the different emulators installed:

image image

image

You may notice that I talk/write a lot about Android. This is not that I dont want to try iOS but to be able to test iOS, you need a Mac (with Xamarin.iOS installed on it) to play the role of a proxy between your PC and the target device. Unfortunately, as I don’t have a such device, I’m not able to try and test that part (if a Apple evangelist read my blog and want to offer me a Mac, feel free to him to do so ;-)

The first time you’ll start an Android emulator, you’ll see this message:

image

Trust me, this is true! Indeed, the first time the emulator starts, the IDE need to deploy on it the Mono Shared Runtime and the Platform Framework corresponding to the API level that will be targeted by your application. So, in my case, the initial start was up to 7 minutes ! Of course, once the emulator is started, the deployments are more faster.

 

A first look of the development part

Each page, of an Android application, is represented by an Activity object. This is the equivalent of the Page objects on Windows (Phone) apps. To define the activity that need to be launched on the first start, you need to put the MainLauncher property to true:

[Activity(Label = "AndroidApplication1", MainLauncher = true, Icon = "@drawable/icon")]
public class Activity1 : Activity
{
}

From the point of view of a XAML developer, the development is quite similar. Indeed, on the XAML side, we have the XAML part that defines the UI and the code-behind that corresponds to the app logic. Well, here, this is the same: the activity corresponds to the code-behind part and the XAML part will be associated to the AXML (no, it’s not a typo) files that we will see more in details later.

On the activity, the method OnCreate need to be override to add our own logic. This method is called when the activity is starting so this is where we’ll define our user interface, etc.:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);
}

To define the user interface, we can do it using 2 ways:

  1. By using C# code
  2. By using XML code.

The first way consists in building the GUI by code:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    var btn = new Button(this);
    btn.Text = "Hello World!";
    btn.Click += (sender, args) => { };

    SetContentView(btn);
}

image

Even if that works, this is not the most useful way (in particular to create complex UI). So we’ll prefer the XML way.

Each project contains a “Resources” folder that is composed by a set of sub-folders:

  1. Drawable: contains all the resources (images for example) that need to be used in the app
  2. Layout: contains all the layouts that will be designed by the developer
  3. Values: contains all the strings resources available

To add a new view, simply right clic on the Layout folder and select Add –> New item –> Android Layout:

image

The screen that appears offers a visual designer where you can drag and drop controls from the toolbox to create your custom UI:

image

If you click on the “Source” button (located at the bottom of the view), you’ll be able to see the XML representation of the GUI. So, like for the XAML part, the visual designer is just here to serialize the XML content and render it on a surface view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:minWidth="25px"
    android:minHeight="25px">
    <Button
        android:text="Button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button1" />
</LinearLayout>

You may notice the particular syntax used to specify the value of the id property: @+id/button1. This syntax tells the parser to generate a resource with the id indicated so, on the file Resource.Designer.cs (which is refreshed after all builds and which contains all the resources values as strongly type properties) a property is automatically added:

public partial class Id
{
    // aapt resource value: 0x7f050001
    public const int MyButton = 2131034113;

    // aapt resource value: 0x7f050000
    public const int button1 = 2131034112;

    static Id()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private Id()
    {
    }
}

For the strings values (of the buttons, labels, etc.), you have 2 choices: you can hardcode the value and set it to the dedicated property (for example, the Text property of the button) or you can use a similar principle as the id property. Indeed, here is a valid code to set the text property:

<Button
        android:text="@string/TestButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/button1" />

So again, we tell the Android parser to generate a dedicated property to the resources file:

public partial class String
{
    // aapt resource value: 0x7f040001
    public const int ApplicationName = 2130968577;

    // aapt resource value: 0x7f040000
    public const int Hello = 2130968576;

    // aapt resource value: 0x7f040002
    public const int TestButton = 2130968578;

    static String()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private String()
    {
    }
}

But this time, this is a bit different. The String class contains the property corresponding to the string resources we want to use but we have to define the values of these resources. To do so, we need to open and edit the file Strings.xml which is in the subfolder Values of the folder Resources:

 image

The content of this file is a simple list of key/value:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="Hello">Hello World, Click Me!</string>
    <string name="ApplicationName">AndroidApplication1</string>
    <string name="TestButton">My Super Button!</string>
</resources>

Using this system, it’s easy to create a localized version of your application. In the Resources folder, just add a folder “Values-XX” where XX corresponds to the two-letter language code (if you want to support multiples locales of the same language, add the two-letter region code prefixed by the –r letter, for example: Values-fr-rFR for the French France locale; Values-fr-rCA for the French Canadian locale, etc.):

 image

Add a new XML file on the newly created folder (be sure to set its Build Action property to AndroidResource) and just translate the content:

image  image

OK so now that our user interface is almost finished (eventually using string resources for the different labels), we need to display it! To do that, let’s go back to the code of the activity and just modify the parameter of the SetContentView to use our newly interface:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);
}

Again, after finishing the user interface, the parser generates a dedicated property so we can manipulate it:

public partial class Layout
{
    // aapt resource value: 0x7f030000
    public const int demolayout = 2130903040;

    // aapt resource value: 0x7f030001
    public const int Main = 2130903041;

    static Layout()
    {
        global::Android.Runtime.ResourceIdManager.UpdateIdValues();
    }

    private Layout()
    {
    }
}

image

Your view is now display on screen but you may wonder how you can interact with it so you can retrieve user inputs (clicks con button, etc.). For that, you’ll need to use the FindViewById method:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);

    var button = FindViewById<Button>(Resource.Id.button1);
}

This method takes in parameter the id of the control you want to manipulate through code (and you can notice, once again, the use of the Resource.Id nested class, which contains all the ids of the graphical elements). Once you get access to the controls, you can manipulate them easily:

protected override void OnCreate(Bundle bundle)
{
    base.OnCreate(bundle);

    // Set our view from the "demolayout" layout resource
    SetContentView(Resource.Layout.demolayout);

    var button = FindViewById<Button>(Resource.Id.button1);
    button.Click += (sender, args) => SetContentView(Resource.Layout.Main);
}

You may also wonder how to access to some assets resources you can embed on the application. To do so, you have 2 choices. For the image files, you need to put them on the “Drawable” folder. After the build, the file Resource.Designer.cs will be updated (as we seen before). Then, to use your new file, simply use it as before:

<ImageView
        android:src="@drawable/Yoda"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/imageView1" />

Here, for the src property, I access to the Yoda file within the “Drawable” folder:

image image

For the other types of files (text files, sound files, video files, etc.), you need to put them on the Assets folder. Files placed on that folder will have a build definition set to AndroidAsset. To be able to use them, you need to call one of the methods of the Asset API of the AssetManager (Asset.Open, Asset.OpenFd, etc.):

var button = FindViewById<Button>(Resource.Id.button1);
button.Click += (sender, args) =>
{
    var assets = Assets.List(string.Empty);
    if (assets.Any())
    {
        var videoFilename = assets.FirstOrDefault(a => a.EndsWith(".mp4"));
        if (!string.IsNullOrWhiteSpace(videoFilename))
        {
            var fileDescriptor = Assets.OpenFd(videoFilename);

            var player = new MediaPlayer();
            player.SetDataSource(fileDescriptor.FileDescriptor, fileDescriptor.StartOffset, fileDescriptor.Length);
            player.Prepare();
            player.Start();
        }
    }
};

To be able to perform some actions, you might need to set the desired required permissions on the Android Manifest file. To do that, open the properties of your project and select the tab “Android Manifest”:

image

In the previous screenshot, the SEND_SMS permission is selected. So the application is free to write code that will send SMS:

SmsManager.Default.SendTextMessage("0123456789", null, "First SMS from Xamarin", null, null);

Without selected this permission, the code throws an exception (one thing I regret currently about exceptions: we don’t have a lot of information about the exact issue):

image

On the project properties, you can also look at the different options you can change like, for example, the particular platforms for which your application will be available or the API version needed to be able to run your app:

image

Some actions you’ll need perform will not need special permissions, even if you think there are needed. Indeed, let’s re-write the sample to send a SMS (don’t forget to uncheck the dedicated permission):

var phoneNumber = Android.Net.Uri.Parse("smsto:0123456789");
var smsIntent = new Intent(Intent.ActionSendto, phoneNumber);
smsIntent.PutExtra("sms_body", "First SMS from Xamarin");
StartActivity(smsIntent);

If you execute this code, you’ll note that there are no errors/exceptions:

image

But how is it possible, as we don’t select the right permission ?! In fact, this is because this sample use an Intent (Android.Content.Intent):

image

An Intent is a kind of concept that is used to say: “Hey, do the following but don’t do it automatically: use a dedicated application to do that!”. So, basically, it’s not your code that performs the action, it’s another app. An intent generally has two pieces of information associated with it; first, what the intent is (a phone call, a camera ), and second, what data does the intent need (such as a phone number) to perform the intention.

That’s why the following code, which use an Intent, does not need special permissions (although it access special information such battery data):

var filter = new IntentFilter(Intent.ActionBatteryChanged);
var battery = RegisterReceiver(null, filter);
int level = battery.GetIntExtra(BatteryManager.ExtraLevel, -1);
int scale = battery.GetIntExtra(BatteryManager.ExtraScale, -1);

var batteryLevel = Math.Floor(level * 100D / scale);

int status = battery.GetIntExtra(BatteryManager.ExtraStatus, -1);
var isCharging = status == (int)BatteryStatus.Charging || status == (int)BatteryStatus.Full;

// How are we charging?
int chargePlug = battery.GetIntExtra(BatteryManager.ExtraPlugged, -1);
var usbCharge = chargePlug == (int)BatteryPlugged.Usb;
var acCharge = chargePlug == (int)BatteryPlugged.Ac;

 

Access to the user’s contacts

To be able to access to the user’s contacts, it’s pretty easy. We’ll use the ManagedQuery API to query the contact’s properties:

var uri = ContactsContract.Contacts.ContentUri;

string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName, };
var cursor = ManagedQuery(uri, projection, null, null, null);

var items = new List<string>();

if (cursor.MoveToFirst())
{
    do
    {
        items.Add(cursor.GetString(cursor.GetColumnIndex(projection[1])));

    }
    while (cursor.MoveToNext());
}

The API takes in parameters the list of properties you want to retrieve. In the previous code, we load the Id and DisplayName properties and we add the last one on a list of string objects. Of course, when using the ManagedQuery object, it’s possible to filter the results:

var uri = ContactsContract.Contacts.ContentUri;

string[] projection = { ContactsContract.Contacts.InterfaceConsts.Id, ContactsContract.Contacts.InterfaceConsts.DisplayName, };
var cursor = ManagedQuery(uri, projection, null, null, null);

var items = new List<string>();

if (cursor.MoveToFirst())
{
    do
    {
        items.Add(cursor.GetString(cursor.GetColumnIndex(projection[1])));

        var userId = cursor.GetString(cursor.GetColumnIndex(projection[0]));
        var userEmailCursor = this.ManagedQuery(ContactsContract.CommonDataKinds.Email.ContentUri, null, ContactsContract.CommonDataKinds.Email.InterfaceConsts.ContactId + "=" + userId, null, null);
        if (userEmailCursor.Count > 0)
        {
            while (userEmailCursor.MoveToNext())
            {
                var userEmail = userEmailCursor.GetString(userEmailCursor.GetColumnIndex(ContactsContract.CommonDataKinds.Email.InterfaceConsts.Data));
            }
        }

    }
    while (cursor.MoveToNext());
}

Ok so now, we have a list of the contacts stored in memory but we need to find a way to display it on the screen. For that, we’ll replace the base type for the current activity by the ListActivity. This is a particular activity type that expose a ListAdapter object, which allow you to directly displays a list of items on the screen using a particular template:

ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, items);

As its name suggests, the SimpleListItem1 display the items using a simple list:

image

If you want to display the items with some Checkboxes, you have just to use SimpleListItemsSingleChoice:

ListAdapter = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItemSingleChoice, items);

Which displays the following:

image

So, by changing a simple property, you can change the display of your items! If you want to know which item is clicked by the user, you just have to override the OnListItemClick method (available because we are on a ListActivity):

protected override void OnListItemClick(ListView l, View v, int position, long id)
{
    var item = items[position];

    Android.Widget.Toast.MakeText(this, item, ToastLength.Short).Show();
}

 

Of course, there are a lot of other things that you can do in your applications but I hope this first overview gave you all the pointers you need to start !

Happy (Xamarin) coding!

The videos of the sessions I’ve animated during the last TechDays 2012 in Paris, France have been published and are now available:

  1. MVVM de A à Z
  2. WPF 4.5: Quoi de neuf pour les développeurs ?

The last session (“Améliorez votre productivité XAML en entreprise”) has not been published but I’ll update my post as soon as  you’ll be able to see it.

 

Happy coding!

As I’ve explained before, I’ll be presenting 3 sessions during the next TechDays in France.

One of the session is entitled “Améliorer votre productivité XAML en entreprise” and we are currently working on it. If you plan to attend to our session (or to TechDays), we want to learn from you: we give you the opportunity to let us know what you want to see in the session !

If you have any particular needs or if you have some subjects that you want to see covered in the session, let me know (in a comment) and we’ll try do our best !

Thanks and don’t forget: if you plan to come in TechDays 2012, feel free to come to see me.

 

Happy coding!

Next month (7, 8 and 9 February), Microsoft France will organize the most important IT event of the year in the country: the Microsoft TechDays 2012 !

During the event, I’ll be presenting 3 sessions:

  1. WPF 4.5 : Quoi de neuf pour les développeurs ? (RDA105)
  2. MVVM de A à Z (RDA106)
  3. Améliorer votre productivité XAML en entreprise ! (RDA201)

If you are in Paris and attending the event, feel free to come to meet me and talk about WPF, Silverlight, Windows Phone and other XAML stuff !

 

See you there!

Since Visual Studio 2008 (and maybe before), it’s possible for developers to generate sample data for the database they are using to develop applications. This feature is really useful to test some scenarios like pagination, load test, etc.

To start, take a look at the following diagram that represent the tables which we are going to use in the article:

image

It’s a pretty simple example but, as you can see, there is a foreign key between the 2 tables and that’s the good part: Visual Studio will be able to generate data and take care of the foreign keys for you !

To populate your database, you first need to add a SQL Server Database Project:

image

Import the content of your database in your project then, right click on the project that has just been created and choose to add a new data generation plan:

image

The screen that appear display all the tables in your database and allow you to specify how many row you want to insert:

image

If your right click on one of the previous line, you can even display a preview of the data that will be generated in your database:

image

As you can see, the “Id” column will not be generated because its value is auto-generated by the database during each insertion:

image

Now, if you press F5, you’ll see that the data are generated for your database:

image

A look in the database values (using SQL Server Management Studio) can confirm that all is OK:

image

We can see that the tables are correctly populated, even for the “FrequencyId”, which is the foreigh key but well filled in !

This is very performant and useful but imagine that some of your SQL tables already contains some data: you don’t want to delete them before generating the sample data:

image

If you try to run your data generation plan, you’ll encounter the following error:

image

Of course, you need to have selected “No” in the MessageBox asking you if you want to delete the data that are currently in the database:

image

After thinking a bit, it appears that the error is normal. Indeed, our data generation plan will insert some data in the “Frequency” table and so, the first index will start from 1. But, as we have already have some data in the table, we cannot insert a duplicate key.

To prevent this error, we need to specify that 0 row will be inserted:

image

But it’ not enough. Indeed, we need to ensure that the data inserted in the column ”FrequencyId” contains good data (i.e. good reference to the data from the Frequency table). To do that, select  the line “NewsPaper” and you’ll see that the “FrequencyId” is actually a foreign key:

image

Change that to select “Data bound generator” and, in the properties (F4), specify the connection information. This property is used to indicate to Visual Studio where to get the data to populate this column. Then, in the “Select Query” property, enter the SQL request that will be used to get the id corresponding to FrequencyId:

image

Automatically, the data generation plan know that to populate the FrequencyId column of the NewsPaper table, it need to get a random value from the SQL request:

image

Now, press the F5 key (choose to don’t delete the data from the database) to insert the data:

image

If you look in the database, you can see that the data has been effectively correctly inserted and, the most important, that the foreign key values (the “FrequencyId” column) contains only values taken from the “Frequency” table:

image

As you’ve seen in the article, generating sample data for your database is pretty simple and a lot of more complex scenarios can be covered….. Maybe I’ll talk about them a bit later !

Happy coding!