[Xamarin] Scanning QRCode in a Xamarin.Forms application

September 29th, 2014 | Posted by Tom in .NET | Article | Xamarin - (0 Comments) | Read: 135

Scanning QRCodes (or barcodes) in a Xamarin.Forms application is really easy thanks to a well-know project ZXing, that has been ported to Xamarin (and for all the devices: iOS, Android and Windows Phone).

 

To implement the feature, first add a reference to the ZXing component to your projects. Then, as always, we need to find a way to communicate between the Forms project (that contains the logic) and the various UI projects. To solve this, we’ll used the DependencyService to register an interface and create the various implementations.

The interface is pretty simple:

public interface IQrCodeScanningService
{
    Task<string> ScanAsync();
}

And here is the implementation for the Windows Phone project:

public class QrCodeScanningService : IQrCodeScanningService
{
    public async Task<string> ScanAsync()
    {
        var scanner = new ZXing.Mobile.MobileBarcodeScanner(App.RootFrame.Dispatcher);
        var scanResults = await scanner.Scan();

        return scanResults.Text;
    }
}

And now, let’s take a look to the implementation for the Android project (of course, it’s also possible to create an iOS implementation):

public class QrCodeScanningService : IQrCodeScanningService
{
    public async Task<string> ScanAsync()
    {
        var scanner = new ZXing.Mobile.MobileBarcodeScanner(Application.Context);
        var scanResults = await scanner.Scan();

        return scanResults.Text;
    }
}

As you can see, each version is particular (the constructor of the MobileBarcodeScanner takes a different parameters, according to the platform).

For each implementation, don’t forget to add the Dependency attribute so the DependencyService can register the interface and the implementation:

// Windows Phone
[assembly: Dependency (typeof(QrCodeScanningService))]
namespace QrCodeScanningWithXamarin.WinPhone.Helpers

// Android
[assembly: Dependency(typeof(QrCodeScanningService))]
namespace QrCodeScanningWithXamarin.Droid.Helpers

And now, in the Forms project (Shared or portable), we can use the DependencyService to retrieve the instance of the class that implement our interface:

var scanButton = new Button
{
    Text = "Launch scan"
};
scanButton.Clicked += async (sender, args) =>
{
    var url = await DependencyService.Get<IQrCodeScanningService>().ScanAsync();

    Device.OpenUri(new Uri(url));
};

Launch your application and click on the button to display the overlay allowing the user to scan a QRCode or Barcode. Once the view appears on the screen, click on it and, after the autofocus is performed, the scan is done and the results are returned so you can use them (display them, launch the URL, etc.)

 

Happy coding!

Since Windows 8, it’s possible to share uris, files, images, etc. using the Share contract:

var dataTransferManager = DataTransferManager.GetForCurrentView();
dataTransferManager.DataRequested += this.ShareStorageItemsTextHandler;

private async void ShareStorageItemsTextHandler(DataTransferManager sender, DataRequestedEventArgs args)
{
    DataRequest request = args.Request;

    request.Data.Properties.Title = "Sample";
    request.Data.Properties.Description = "Description";
}

Thanks to the unification of Windows 8.1 and Windows Phone 8.1, we can now do the same to share items on Windows Phone.

While I was testing that on an Windows Phone 8.1 (WinRT) application, I found that if you want to share an image, you’ll need to share the StorageFile instead. Indeed, the following will not work:

private async void ShareStorageItemsTextHandler(DataTransferManager sender, DataRequestedEventArgs args)
{
    DataRequest request = args.Request;

    request.Data.Properties.Title = "Sample";
    request.Data.Properties.Description = "Description";

    var deferral = request.GetDeferral();

    try
    {
        var fileToShare = await this.GetImageFileAsync("Sample.jpg");

        request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromStream(fileToShare);
        request.Data.SetBitmap(RandomAccessStreamReference.CreateFromStream(fileToShare));
    }
    finally
    {
        deferral.Complete();
    }
}

Well, in fact, if you try to share, you’ll see that it’s working except that the image is not displayed/used. This is due to the fact that when an application implement the Share contract (in receive mode), it needs to indicate which file format it’s able to manage: uris, bitmap, file, text, etc. The native Windows Phone’s apps does not seems to manage the Bitmap format of the Share contract so you’ll need to used the following version:

private async void ShareStorageItemsTextHandler(DataTransferManager sender, DataRequestedEventArgs args)
{
    DataRequest request = args.Request;

    request.Data.Properties.Title = "Sample";
    request.Data.Properties.Description = "Description";

    var deferral = request.GetDeferral();

    try
    {
        var fileToShare = await this.GetImageFileAsync("Sample.jpg");
        var storageFileToshare = await this.GetStorageFileForImageAsync("Sample.jpg");

        request.Data.Properties.Thumbnail = RandomAccessStreamReference.CreateFromStream(fileToShare);
        request.Data.SetBitmap(RandomAccessStreamReference.CreateFromStream(fileToShare));

        // On Windows Phone, share StorageFile instead of Bitmaps
        request.Data.SetStorageItems(new List<StorageFile> { storageFileToshare });
    }
    finally
    {
        deferral.Complete();
    }
}

With that code, I’m able to share the image, either as an image or as a file: the OS will choose the available targets according to the format I decided to use.

 

Happy coding!

The Binding feature of Xamarin is one of the most powerful one that I’ve seen when playing with the product. Indeed, it allows you to reuse any Java libraries (available as JAR files) directly from your application (written in C#).

This wonderful feature is made available by the Xamarin team thanks to the Managed Callable Wrappers. If you look at my first article about Xamarin, you’ll learn that the MCW are just JNI (Java Native Interface) bridges, some generated code, that are used every time the managed code needs to invoke Java code (on the other hand, when the Java code needs to call managed code, it’s another bridge, named Android Callable Wrapper, that is used).

 

Using the feature is really simple thanks to Visual Studio (or Android Studio). First, you need to create an Android Bindings Library:

image

Once this is done, the IDE will create a project containing the following elements:

  • A folder “Jars” that contains all the JAR files you want to reuse
  • A folder “Transforms” that contains some configuration files used to control the wrappers’ generation
  • A folder “Additions”, that can contains C# code which can be added to the generated classes

image

As we told previously, we’ll be able to reuse any Java library so, for this article, I’ve just grabbed a copy of the Java Image Library available here: http://www.jhlabs.com/ip/filters/download.html

Once you’ve downloaded the JAR file, simply drop it to the Jars folder and set its “Build Action” to “InputJar”:

image

This tells Xamarin to create a bridge for each Jar files defined using this build action.

So now, you’ve basically finished your job. Indeed, most of time, you have nothing else to perform but just compile to get a .NET DLL that can be referenced to your Xamarin.Android application.

If you care, you can take a look to the folder obj\Debug\generated\src to see the generated files used to create the DLL:

image

Sometimes, you might need to solve some issues due to the code generation. Indeed, folks at Xamarin performs 99% of the code generation but there are some things you need to change in order to compile correctly.

In our case, here is the result when we tried to compile our project:

image

Holy crap, it’s not working! According to the error message, it looks like we have a member of a class with the same name as its enclosing type. If we perform a double click on the error message, Visual Studio opens the generated file on the error:

image

Interesting right? We can see that the Histogram class that has been generated has a property named Histogram too, which is not allowed. So we need to find a way to rename this property automatically while performing code generation so the code could compile correctly.

To do this, we need to check in the “Transforms” folder to see the files available for the code generation customization:

  • EnumFields.xml is used to map a Java int value to a .NET enum
  • EnumMethods.xml is used to change the generation of methods’ parameters
  • Metadata.xml is used to change names of types, members, etc.

image

As we want to change the name of a class member, we need to edit the file Metadata.xml to instruct the code generator to change the name of the field Histogram of the type Histogram.

So we just add the following:

<attr path="/api/package[@name='com.jhlabs.image']/class[@name='Histogram']/field[@name='histogram']" name="name">Current</attr>

 

Doing so, we just tell the code generator to change the name of the field Histogram of the type Histogram and to replace it by “Current”. Now, if we build the library, we don’t get any errors and if we look on the generated file, we can see that the property’s name has changed:

image

Now, we can test our library! For that, it’s simple: just create a new Xamarin.Android application and add a reference to your library:

image

Note: If you have some issues when adding the reference as a project reference, try to add it as a DLL instead (see here)

Then, using the library is as simple as using any existing libraries:

image

Even if that works fine, there are at least 2 things that I don’t like:

    • The namespace are the Java’s one
    • The name of the parameters are p0, p1, p2, etc.

Changing the namespace is straightforward. Once again, we need to edit Metadata.xml:

<attr path="/api/package[@name='com.jhlabs.image']" name="managedName">ImageProcessingLibrary</attr>

Thanks to this line, we are able to change the name of the .NET namespace (without touching of the Java’s one):

image => image

Again, as the name of the namespace change, we need to modify the code of our test application:

image

Now, let’s see how to change the name of the parameters. This one is not complex but might take the most of time, as you may want to do it for all the methods.

Again, all will be done in Metadata.xml, by adding the following line (one line for each methods’ parameters you want to rename):

<attr path="/api/package[@name='com.jhlabs.image']/class[@name='LightFilter']/method[@name='addLight']/parameter[@name='p0']" name="name">lightToAdd</attr>
<attr path="/api/package[@name='com.jhlabs.image']/class[@name='LightFilter']/method[@name='removeLight']/parameter[@name='p0']" name="name">lightToRemove</attr>

We just instruct the code generator so in the namespace com.jhlabs.image, find the class LightFilter, look for the methods addLight and removeLigh and rename the parameter initially named p0.

Here is the code that has been generated:

image image

And when using the Intellisense, we can see the correct name for our parameters:

image

 

Previously, I talked about the “Additions” folder which can contains code that will be added to the generated classes.

Using this feature is as simple as writting code files and put them in the folder (all the magic is performed at compilation). All the classes generated by the code generator are marked as partial so it’s easy to add custom code. For example, add a file containing the following code:

public partial class LightFilter
{
    public void AddLightByName(string lightName)
    {
        //
    }
}

Now, if you compile and use your library, you’ll be able to use the new method AddLightByName:

image

 

As you can see, the Binding feature is really cool and easy to use! Of course, most of the job is performed under the cover by the Xamarin tools but it’s very flexible and configurable so let’s try it: you won’t regret it!

If you want to know more (specially about the possible errors you may encountered), you can check the official documentation.

Happy coding! :)

As I’m working on a small ASP.NET MVC 5 application, I wanted to deploy it on Windows Azure to test it. Thanks to Visual Studio, the deployment was really easy but, as soon as I tried to browse the website, I received the following error message:

Could not load file or assembly ‘Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35′ or one of its dependencies. The system cannot find the file specified.

 image

After searching a bit, it appears that the error is due to the reference Microsoft.Web.Infrastructure.dll that is not deployed automatically with your app. To resolve the issue, just select the reference, go to the properties and set “Copy Local” to true:

image

Once this is done, deploy your website again and now, it should works fine!

 

Happy coding!

I’m proud to announce that my second MSDN article has been finally published in the August issue of MSDN Magazine!

Entitled “Build MVVM Apps with Xamarin and MvvmCross”, the article will let you know all you need to start developping MVVM apps with Xamarin and MvvmCross.

I hope you’ll like it!

 

Happy coding!

[VSX] How to be notified of the debug events ?

July 18th, 2014 | Posted by Tom in .NET | Article | Visual Studio | VSX - (0 Comments) | Read: 468

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!

Some parts of the latest versions of Visual Studio are developed using MEF (Managed Extensibility Framework), allowing developers to easily create addins  to extend the features of the IDE. On this article, we’ll cover the basics to add custom tooltips to the Visual Studio’s editor.

A tooltip is a small amount of information which appears just under the mouse, when this one is no longer moving:

image

To create a custom tooltip, we first need to create a class that implement IMouseProcessorProvider:

[Export(typeof(IMouseProcessorProvider))]
[TextViewRole(PredefinedTextViewRoles.Document)]
[ContentType("xaml")]
[Name("MyCustomTooltip")]
internal sealed class CustomTooltipHandlerProvider : IMouseProcessorProvider
{
}

Using MEF, we export the type IMouseProcessorProvider so Visual Studio will know that it can loads the content of this file as a plugin.

The ContentType attribute is used to indicate for which type of document the tooltip will be available. There are a lot of default content types but you can easily creates your own if needed. In our case, the plugin will be loaded for the XAML files.

Once this is done, we have to implement the content of the interface so this is the method GetAssociatedProcessor, returning the MouseProcessorBase that will be used to display our tooltip:

[Import]
public IToolTipProviderFactory ToolTipProviderFactory { get; set; }

[Import]
public ITextStructureNavigatorSelectorService NavigatorService { get; set; }

[Import]
internal IClassifierAggregatorService AggregatorService { get; set; }

public IMouseProcessor GetAssociatedProcessor(IWpfTextView view)
{
    return new CustomTooltipMouseProcessor(view, this.ToolTipProviderFactory, this.NavigatorService.GetTextStructureNavigator(view.TextBuffer), this.AggregatorService.GetClassifier(view.TextBuffer));
}

Now, let’s take a look at the CustomTooltipMouseProcessor class that we have to create. It’s a simple class that derives from MouseProcessorBase:

internal class CustomTooltipMouseProcessor : MouseProcessorBase
{
    private readonly IWpfTextView _view;

    private readonly IToolTipProvider _toolTipProvider;
    private readonly ITextStructureNavigator _navigatorService;
    private readonly IClassifier _classifier;

    private readonly ICollection<FontFamily> _systemFonts; 

    private bool IsToolTipShown { get; set; }

    internal CustomTooltipMouseProcessor(IWpfTextView view, IToolTipProviderFactory toolTipProviderFactory, ITextStructureNavigator navigatorService, IClassifier classifier)
    {
        this._view = view;
        this._toolTipProvider = toolTipProviderFactory.GetToolTipProvider(this._view);
        this._navigatorService = navigatorService;
        this._classifier = classifier;

        this._systemFonts = Fonts.SystemFontFamilies;

        this.IsToolTipShown = false;
    }
}

The most important part of this class is the PreProcessMouseMove method, that will handle any mouse move in the editor:

public override void PreprocessMouseMove(MouseEventArgs e)
{
    var colorConverter = new ColorConverter();

    foreach (ITextViewLine viewLine in this._view.TextViewLines)
    {
        // Get the span for each line
        var lineSpan = new SnapshotSpan(viewLine.Start, viewLine.End);

        // Get the classification for each span
        var spans = this._classifier.GetClassificationSpans(lineSpan);
        foreach (var span in spans)
        {
            // If we are on a XAML attribute
            if (span.ClassificationType.Classification == "XAML Attribute Value")
            {
                // Get the attribute value
                var xamlAttributeValue = span.Span.GetText().Replace("\"", "");

                // Check if the attribute's value is a valid color
                if (colorConverter.IsValid(xamlAttributeValue))
                {
                    #region Tooltip management for FontFamily

                    var convertedColor = colorConverter.ConvertFromInvariantString(xamlAttributeValue);
                    if (convertedColor != null)
                    {
                        var xamlColor = (Color)convertedColor;

                        var spanAtMousePosition = Helpers.SpanHelpers.GetSpanAtMousePosition(this._view, this._navigatorService);
                        if (spanAtMousePosition.HasValue)
                        {
                            var textAtMousePosition = spanAtMousePosition.Value.GetText();

                            if (!string.IsNullOrWhiteSpace(textAtMousePosition))
                            {
                                if (xamlAttributeValue.Contains(textAtMousePosition))
                                {
                                    e.Handled = true;

                                    if (!this.IsToolTipShown)
                                    {
                                        this.IsToolTipShown = true;

                                        var copyHexColorHyperlink = new Hyperlink(new Run("Copy"));
                                        copyHexColorHyperlink.Click += (sender, args) =>
                                        {
                                            Clipboard.SetText(xamlColor.ColorToHexString());

                                            this._toolTipProvider.ClearToolTip();
                                        };

                                        this._toolTipProvider.ClearToolTip();
                                        this._toolTipProvider.ShowToolTip(spanAtMousePosition.Value.Snapshot.CreateTrackingSpan(spanAtMousePosition.Value.Span, SpanTrackingMode.EdgeExclusive),
                                            new Border
                                            {
                                                Background = new SolidColorBrush(Colors.LightGray),
                                                Padding = new Thickness(10),
                                                Child = new StackPanel
                                                {
                                                    Orientation = Orientation.Horizontal,
                                                    Children =
                                                    {
                                                        new Rectangle
                                                        {
                                                            Height = 30,
                                                            Width = 30,
                                                            Fill = new SolidColorBrush(xamlColor)
                                                        },
                                                        new TextBlock
                                                        {
                                                            Margin = new Thickness(10, 0, 0, 0),
                                                            Inlines =
                                                            {
                                                                //new Run(xamlAttributeValue),
                                                                //new LineBreak(),
                                                                new Run(xamlColor.ColorToHexString()),
                                                                new Run(" ("),
                                                                copyHexColorHyperlink,
                                                                new Run(")"),
                                                                new LineBreak(),
                                                                new Run(string.Format("{0}", xamlColor.ColorToRgbString())),
                                                            }
                                                        }
                                                    }
                                                }
                                            }, PopupStyles.PositionClosest);
                                    }

                                    return;
                                }
                            }
                        }
                    }

                    #endregion
                }
                // Check if the attribute's value is a valid color
                else if (this._systemFonts.Any(ff => ff.Source == xamlAttributeValue))
                {
                    #region Tooltip management for FontFamily

                    var xamlFontFamily = this._systemFonts.First(ff => ff.Source == xamlAttributeValue);

                    var spanAtMousePosition = Helpers.SpanHelpers.GetSpanAtMousePosition(this._view, this._navigatorService);
                    if (spanAtMousePosition.HasValue)
                    {
                        var textAtMousePosition = spanAtMousePosition.Value.GetText();
                        if (!string.IsNullOrWhiteSpace(textAtMousePosition))
                        {
                            // FontFamily can have whitespace in their name.
                            if (xamlAttributeValue.Contains(textAtMousePosition))
                            {
                                e.Handled = true;

                                if (!this.IsToolTipShown)
                                {
                                    this.IsToolTipShown = true;

                                    this._toolTipProvider.ClearToolTip();
                                    this._toolTipProvider.ShowToolTip(spanAtMousePosition.Value.Snapshot.CreateTrackingSpan(spanAtMousePosition.Value.Span, SpanTrackingMode.EdgeExclusive),
                                        new Border
                                        {
                                            Background = new SolidColorBrush(Colors.LightGray),
                                            Padding = new Thickness(10),
                                            Child = new StackPanel
                                            {
                                                Orientation = Orientation.Vertical,
                                                Children =
                                                {
                                                    new TextBlock
                                                    {
                                                        Inlines =
                                                        {
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 10), FontSize = 10, FontFamily = xamlFontFamily },
                                                            new LineBreak(),
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 12), FontSize = 12, FontFamily = xamlFontFamily },
                                                            new LineBreak(),
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 15), FontSize = 15, FontFamily = xamlFontFamily },
                                                            new LineBreak(),
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 18), FontSize = 18, FontFamily = xamlFontFamily },
                                                            new LineBreak(),
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 20), FontSize = 20, FontFamily = xamlFontFamily },
                                                            new LineBreak(),
                                                            new Run{ Text = string.Format("{0} ({1})", xamlFontFamily.FamilyNames[this._view.VisualElement.Language], 25), FontSize = 25, FontFamily = xamlFontFamily },
                                                        }
                                                    }
                                                }
                                            }
                                        }, PopupStyles.PositionClosest);
                                }

                                return;
                            }
                        }
                    }

                    #endregion
                }
            }
        }
    }

    this._toolTipProvider.ClearToolTip();
    IsToolTipShown = false;
}

This method has a lot of lines of code but, basically, the process is simple:

  1. For each line in the editor, we get the line
  2. We then get the classifications of items on the line
  3. For each classification, we check if we are on a XAML attribute
  4. If yes, we check if this attribute’s value is a color or font family
  5. If yes, we get the text under the mouse
  6. If the text under the mouse is contained by the value of the XAML attribute, we proceed the next part of the code, which displays a custom tooltip using the method ShowToolTip of the ToolTipProvider

Thanks to the use of WPF in the IDE, we can display cool new tooltips (in my case, i’ve coded them but you can easily use UserControls).

When running this code, we can see that Visual Studio will launch and when we are in a XAML document, hovering a color or font display the new tooltip:

image

image

image

Those of you who are using Resharper or Web Essentials may have recognize some of the same features ;)

As you can see, it’s really easy to develop addins for Visual Studio and this can help you to increase your productivity.

 

Happy coding!

When using Xamarin.Forms, you have a lot of differents pages and layouts available to build your applications.

The TabbedPage is a very good one that allows you to navigate betweend children pages, using tabs. Unfortunately, the control does not offer the possibility to know when the current page is changing (or has changed).

So, a possible workaround, when using this base class, is to add an event handler on the PropertyChanged event and watch for the property CurrentPage. Here is a sample demoing that:

public delegate void CurrentPageChangingEventHandler();
public delegate void CurrentPageChangedEventHandler();

public class ExtendedTabbedPage : TabbedPage
{
    public event CurrentPageChangingEventHandler CurrentPageChanging;
    public event CurrentPageChangedEventHandler CurrentPageChanged;

    public ExtendedTabbedPage()
    {
        this.PropertyChanging += this.OnPropertyChanging;
        this.PropertyChanged += this.OnPropertyChanged;
    }

    private void OnPropertyChanging(object sender, PropertyChangingEventArgs e)
    {
        if (e.PropertyName == "CurrentPage")
        {
            this.RaiseCurrentPageChanging();
        }
    }

    private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "CurrentPage")
        {
            this.RaiseCurrentPageChanged();
        }
    }

    private void RaiseCurrentPageChanging()
    {
        var handler = this.CurrentPageChanging;
        if (handler != null)
        {
            handler();
        }
    }

    private void RaiseCurrentPageChanged()
    {
        var handler = this.CurrentPageChanged;
        if (handler != null)
        {
            handler();
        }
    }
}

To use it, you now just have to register for the event CurrentPageChanging or CurrentPageChanged:

public class MainPage : ExtendedTabbedPage
{
    private readonly OrganizerView _organizerView;
    private readonly AttendeeView _attendeeView;

    private readonly ToolbarItem _refreshToolbarItem;

    public MainPage()
    {
        this.Title = "Meeting Organizer";

        this._organizerView = new OrganizerView();
        this._attendeeView = new AttendeeView();

        this.Children.Add(this._organizerView);
        this.Children.Add(this._attendeeView);

        this._refreshToolbarItem = new ToolbarItem("Refresh", "refresh.png", () =>
        {
            //
        });

        this.CurrentPageChanged += OnCurrentPageChanged;
    }

    private void OnCurrentPageChanged()
    {
        if (this.CurrentPage == this._organizerView)
        {
            this.ToolbarItems.Clear();
        }
        else if (this.CurrentPage == this._attendeeView)
        {
            this.ToolbarItems.Add(this._refreshToolbarItem);
        }
    }
}

Simple but useful !

 

Happy coding!

[Xamarin] How to access user’s contacts ?

March 10th, 2014 | Posted by Tom in .NET | Article | Windows Phone | WPF - (0 Comments) | Read: 1,039

In my previous article about Xamarin, I’ve explained a way to access user’s contact by using the ManagedQuery API. Even if the code is working fine, you may think that it can be a bit “hard” to understand, when the only goal is to query the contacts.

Today, I’ll talk about Xamarin.Mobile, a library that exposes some APIs to access user’s contacts, user’s position and to allow you to, easily, take a picture in your application. The interesting point here is the fact that the API is available for iOS, Android and Windows Phone.

To use Xamarin.Mobile, you need to download the binaries. Thanks to the Components Store available (something that’s a bit similar to Nuget), you can get them easily:

image image

After you hit the “Add to App” button, the component is downloaded and the reference is added to your project:

image image

Once the reference is added, the first step is to add the following “using”:

using Xamarin.Contacts;

Now, by using the AddressBook class, we are able to access to the user’s contacts and we can use LINQ, which provides a more easier and comfortable syntax:

var addressBook = new AddressBook(this);
if (!await addressBook.RequestPermission())
{
    // We don't have the permission to access user's contacts: check if the READ_CONTACTS has been set
}
else
{
    var companyContacts = addressBook.Where(c => c.Organizations.Any(o => o.Name == "Infinite Square"));
    if (companyContacts.Any())
    {
        foreach (var contact in companyContacts)
        {
            var lastName = contact.LastName;
            var firstName = contact.FirstName;
            var thumbnailBitmap = contact.GetThumbnail();
        }
    }
}

As you can see, the code is really easy to understand and maintainable!

 

If you want to know more about Xamarin.Mobile (or just check how does it work), feel free to go to Github, where you’ll be able to find the sources: https://github.com/xamarin/Xamarin.Mobile

 

Happy (Xamarin) coding!

Recently, I was talking with one of my good friend, Matthieu, who explained me how he uses, in WAQS, some Nuget packages to add commands to the PowerShell console. As I like this idea, I decide to take a look at it and it’s really powerful!

So let’s see how it works and let me show you a preview of what you can do :)

Creating the Nuget package

This is the main (but mandatory) step you’ll need to do. For that, I decided to use the tool Nuget Package Explorer that let you to create your package, edit its metadata, add some dependencies, etc.

image

Once you created your package (it’s as simple as click on New –> File), you need to specify what you’ll put in your package. In our case, we want to add some commands to the PowerShell console so we need a script that will run every time a solution/project is opened so we have to add some content to the file init.ps1:

image

We could have choose to put our code in the file install.ps1 but the content of this file is only executed when the Nuget package is installed and not when user open your project in a new instance of Visual Studio (because, in that case, there is no install to perform as the package is already installed). As we want our commands to be always available (not only when the package is installed), we need to use init.ps1 (thanks Matthieu for the trick).

On that file, we’ll perform 2 actions: first, we’ll remove all the previous versions of the module we are developing then we’ll import it (using a module is not always needed but it’s a good thing to split your code in smaller files):

param($installPath, $toolsPath, $package)

foreach ($_ in Get-Module | ?{$_.Name -eq 'VSExtensionsModule'})
{
    Remove-Module 'VSExtensionsModule'
}

Import-Module (Join-Path $toolsPath VSExtensionsModule.psm1)

If the first step is not mandatory (unlike the second one), I recommend you to use it because it’ll prevent your package to be loaded more than 1 time! For the second step, it’ll just import our module to the PowerShell console so now, let’s take a look at the content of that module.

Adding commands to the PowerShell console

Our use case is simple: we want a PowerShell command that will allow us to count, in our project, all the files of a particular extension provided on IntelliSense by the files located on the root folder of the project (yes, I know this is not perfect but it’s just for the demo):

image

To do that, we need to register some code to tell PowerShell to show IntelliSense when user press the Tab key:

Register-TabExpansion 'Get-FilesCount' @{
    'extension' = { Get-Extensions | foreach { $_ } }
}

This code can be read as: “when the user write the command Get-FileCount and press the Tab key, use the method Get-Extensions to get the list of all available extensions and display them on screen”. So the next interesting point is to look at the Get-Extensions method:

function Get-Extensions()
{
    $extensionsList = New-Object Collections.Generic.List``1[string]

    $project = Get-Project
    $projectPath = [System.IO.Path]::GetDirectoryName($project.FullName)

    foreach($file in [System.IO.Directory]::GetFiles($projectPath))
    {
        $fileExtension = [System.IO.Path]::GetExtension($file)
        #$fileExtension = $fileExtension.Substring(1)

        if(!$extensionsList.Contains($fileExtension))
        {
            $extensionsList.Add($fileExtension)
        }
    }

    return $extensionsList
}

This method first starts by creating a generic list of string (List<string>) that will be used to store the list of all extensions. Then, by using the Get-Project method, we get the current active project in Visual Studio and, with the Path.GetDirectoryName method, we retrieve the path to the directory of that project! Then, we iterate through all the files of the folder (be careful here because we don’t use a recursive method) and we get the extension of all the files. That’s all, we are now able to display, on the IntelliSense, the list of all the extensions:

image

Ok so now that the IntelliSense is here, we just need to finish to implement the Get-FilesCount method:

function Get-FilesCount($extension)
{
    $project = Get-Project
    $projectPath = [System.IO.Path]::GetDirectoryName($project.FullName)

    $toExclude = @("\bin", "\obj")

    $files = New-Object Collections.Generic.List``1[string]

    GetFiles $projectPath $toExclude $files

    if($extension -eq $null)
    {
       Write-Host "There are "$files.Count" files on the project."
    }
    else
    {
       $count = 0

       foreach($file in $files)
       {
           if ($file.ToLowerInvariant().EndsWith($extension))
           {
                $count++
           }
       }

       Write-Host "There are "$count" files with the extension '"$extension"' on the project."
    }
}

function GetFiles($path, [string[]]$exclude, $files)
{
    foreach ($item in Get-ChildItem $path)
    {
        if ($exclude | Where { $item.FullName.Contains($_) }) { continue }

        if (Test-Path $item.FullName -PathType Container)
        {
            GetFiles $item.FullName $exclude $files
        }
        else
        {
            $files.Add($item.FullName)
        }
    }
}

The content of the method is pretty simple: we use a recursive method to get all the files from the project and we display the number of files available (or the number of files corresponding to a particular extension).

Finally, we need to export the method of the module:

Export-ModuleMember Get-FilesCount

Once the package is installed on the project, we can use the method in the console:

image

This example might be a bit naive so let’s take a look at a more real sample.

A better example: Get-ImagesFileSizes

This time, we’ll build a better command, that will be used to display the list of all the image’s files (and their size) in your project.

Again, we’ll support the IntelliSense:

Register-TabExpansion 'Get-ImagesFileSizes' @{
    'extension' = { Get-ImagesExtensions | foreach { $_ } }
}

The Get-ImagesExtensions is a simple method (it could be possible to build a more complex one, that display the extension of the image’s files available in the project):

function Get-ImagesExtensions()
{
    $imagesExtensionsList = New-Object Collections.Generic.List``1[string]

    $imagesExtensionsList.Add(".png")
    $imagesExtensionsList.Add(".jpg")
    $imagesExtensionsList.Add(".jpeg")
    $imagesExtensionsList.Add(".bmp")
    $imagesExtensionsList.Add(".gif")

    return $imagesExtensionsList
}

Finally, we need to implement the Get-ImagesFileSizes method. This method will be quite similar to the previous one byt, this time, we’ll access to the Length property of the file:

function Get-ImagesFileSizes($extension)
{
    $project = Get-Project
    $projectPath = [System.IO.Path]::GetDirectoryName($project.FullName)

    $toExclude = @("\bin", "\obj")

    $files = New-Object Collections.Generic.List``1[string]

    GetFiles $projectPath $toExclude $files

    if($files.Count -gt 0)
    {
        if($extension -eq $null)
        {
           foreach($file in $files)
           {
               Write-Host $file ":" (Format-FileSize((Get-Item $file).Length))
           }
        }
        else
        {
            $filesWithExtension = ($files | Where { $_.ToLowerInvariant().EndsWith($extension) })
            if($filesWithExtension.Count -gt 0)
            {
                foreach($file in $filesWithExtension)
                {
                    Write-Host $file ": " (Format-FileSize((Get-Item $file).Length))
                }
            }
            else
            {
                Write-Host "Sorry, there are no image(s) with the following extension" $extension
            }
        }
    }
    else
    {
        Write-Host "Humm.... Looks like there are no images on your project :)"
    }
}

The interesting point here is the Format-FileSize method that he use to format the file size to a human readable value:

#
# Source: http://superuser.com/questions/468782/show-human-readable-file-sizes-in-the-default-powershell-ls-command
#
function Format-FileSize()
{
    param ([int]$size)

    if ($size -gt 1TB)
    {
        [string]::Format("{0:0} Tb", $size / 1TB)
    }
    elseif ($size -gt 1GB)
    {
        [string]::Format("{0:0} Gb", $size / 1GB)
    }
    elseif ($size -gt 1MB)
    {
        [string]::Format("{0:0} Mb", $size / 1MB)
    }
    elseif ($size -gt 1KB)
    {
        [string]::Format("{0:0} Kb", $size / 1KB)
    }
    elseif ($size -gt 0)
    {
        [string]::Format("{0:0} b", $size)
    }
    else
    {
        ""
    }
}

When installed and used on the project, the extension works fine:

image

image

 

As you can see, using Nuget/PowerShell to extend the PowerShell console is really easy (if we omits the fact that you may need to learn the PowerShell :) and you can do a lot of more complex things (dynamically adding resources, create base files for a View/ViewModel in XAML projects, etc.). If you want to learn more, I suggest you to look in WAQS, you’ll have a good overview of what’s possible to do!

 

Happy coding!