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: 439

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: 985

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!

[Windows 8(.1)] Introduction to Prism for the Windows Runtime

February 25th, 2014 | Posted by Tom in .NET | Article | Prism | Windows 8 | WinRT - (0 Comments) | Read: 1,961

Early 2014, the Patterns & Practices teams at Microsoft released a new version of the Prism library, dedicated to the creation of business apps using C# and XAML on Windows 8.1 (a version for Windows 8 already existed since 2013, the team “just” updated the version to add the support of Windows 8.1).

In this article, we’ll provide the basics to use Prism to create a Windows Store application so let’s start !

Architecture

Here is the diagram of a typical Windows Store application that is developed using the Prism library:

 Logical architecture of a Windows Store business app that uses Prism

As you can see, this is a standard architecture: MVVM to separate the concerns of presentation, presentation logic, and model, a data access layer using repositories and some Services proxies to retrieve the data, etc. The good part is that some elements are directly provided by Prism (ViewBase, ViewModelBase, ViewModelLocator, Event Aggregator, etc.) so, you just have to provide the XAML code (View), the logic code (ViewModel) and the business objects (Model).

Creating the application

Creating the application is the same as creating any Windows Store application (File –> New Project) but, once Visual Studio has finished to create the project, you need to add reference to the following Nuget packages:

  • Prism.StoreApps: this is the class library that provides MVVM support with lifecycle management, and core services to a Windows Store app (see here for the list of all the features provided)
  • Prism.PubSubEvents: the Portable Class Library that contains classes that implement event aggregation (again, check here to see the class contains on the library)

image

Once this is done, derive the App class from the MvvmAppBase class, to allow your application to support the MVVM pattern and the core services (navigation, events aggregation, etc.):

sealed partial class App : MvvmAppBase

Don’t forget to change the base class of the file App.xaml too or you’ll get compile errors:

<storeApps:MvvmAppBase
    x:Class="DemoPrism.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DemoPrism"
    xmlns:storeApps="using:Microsoft.Practices.Prism.StoreApps">

</storeApps:MvvmAppBase>

The MvvmAppBase class is an abstract class that define one method that need to be implemented: OnLaunchApplication. This method is used to perform the initial launch of the application so this is where we’ll define the page that’ll be launched on start:

protected override Task OnLaunchApplication(LaunchActivatedEventArgs args)
{
    NavigationService.Navigate("MainPage", null);

    return Task.FromResult<object>(null);
}

This method need to return a Task object so you can use Task.FromResult to return an empty task. To don’t have conflicts with the initial overridden methods, don’t forget to delete the OnLaunched and OnSuspending methods.

The code use the NavigationService property, which is Navigation Service that we can use to perform navigation within the application. Unfortunately, if you try to run this code, you’ll get the following exception:

SNAGHTML2de0d500

Indeed, by default, Prism use a particular convention for the Views: they need to be placed on the “Views” folder. In my case, I used to have the following structure on my applications:

image

So I have a “Views” folder but this folder contains sub-folders containing the big features of the application. So I need to find a way to tell the Prism library to look for the views on that sub-folders. And this can be done by overriding the GetPageType method of the MvvmAppBase class:

protected override Type GetPageType(string pageToken)
{
    var subPageToken = pageToken.Substring(0, pageToken.Length - pageToken.IndexOf("Page", StringComparison.Ordinal));

    var assemblyQualifiedAppType = this.GetType().GetTypeInfo().AssemblyQualifiedName;
    var pageNameWithParameter = assemblyQualifiedAppType.Replace(this.GetType().FullName, this.GetType().Namespace + ".Views.{0}.{1}");
    var viewFullName = string.Format(CultureInfo.InvariantCulture, pageNameWithParameter, subPageToken, pageToken);
    var viewType = Type.GetType(viewFullName);

    return viewType;
}

Now, if I execute the code, the application loads correctly and the page is displayed:

image

Registering services using Dependency Injection

This is not a mandatory steps but Prism has been a long time co-worker of Dependency Injection tools like Unity. So let’s start by adding the Nuget package of your choice (here, I’ll use Unity):

image

Then, declare a Unity container to register and resolve types and instances:

private readonly IUnityContainer _container = new UnityContainer();

You can then override the OnInitialize method of MvvmAppBase to register types and perform any other initialization:

protected override void OnInitialize(IActivatedEventArgs args)
{
    _container.RegisterInstance<INavigationService>(NavigationService);
    _container.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());
}

And, to be able to resolve the types, you just need to override the Resolve method:

protected override object Resolve(Type type)
{
    return _container.Resolve(type);
}

Now, let’s see how we can add the Views and the ViewModels to the application.

Creating a View and its ViewModel

The Views has nothing particular related to the Prism library. You just composed it like you used to do it so this is just XAML content that you defined using Visual Studio or Blend.

To define the ViewModel associated to the view, you can use the ViewModelLocator.AutoWireViewModel property:

xmlns:storeApps="using:Microsoft.Practices.Prism.StoreApps"
storeApps:ViewModelLocator.AutoWireViewModel="true"

Once this property is set to True, the ViewModelLocator will try to instanciate the corresponding ViewModel based on a particular convention: the ViewModels need to be located in the same assembly, in a namespace ended by .ViewModels and the ViewModel name must match the View name and ends with ViewModel. But this is always what you have in your application. Indeed, you can have your ViewModels in a separate assembly or you can have them within the folder containing the views, like I use to have:

image

Fortunately, you can once again change the way Prism is loading your ViewModels, by specifying the ViewModelLocator.SetDefaultViewTypetoViewModelTypeResolver method:

protected override void OnInitialize(IActivatedEventArgs args)
{
    _container.RegisterInstance<INavigationService>(NavigationService);
    _container.RegisterType<IEventAggregator, EventAggregator>(new ContainerControlledLifetimeManager());

    ViewModelLocator.SetDefaultViewTypeToViewModelTypeResolver((viewType) =>
    {
        var subPageToken = viewType.Name.Substring(0, viewType.Name.Length - viewType.Name.IndexOf("Page", StringComparison.Ordinal));

        var assemblyQualifiedAppType = this.GetType().GetTypeInfo().AssemblyQualifiedName;
        var pageNameWithParameter = assemblyQualifiedAppType.Replace(this.GetType().FullName, this.GetType().Namespace + ".Views.{0}.{1}ViewModel");

        var viewFullName = string.Format(CultureInfo.InvariantCulture, pageNameWithParameter, subPageToken, viewType.Name);
        var viewModelType = Type.GetType(viewFullName);

        return viewModelType;
    });
}

Now, if you execute your application and put a breakpoint to the ViewModel’s constructor, you’ll see that the execution is stopped correctly (the ViewModel has been correctly instantiated):

image

Also, thanks to the Dependency Injection we put in place with Unity, we can construct the ViewModel and get, in constructor’s parameters, the type we want to retrieve:

public class MainPageViewModel : ViewModel
{
    private readonly INavigationService _navigationService;
    private readonly IEventAggregator _eventAggregator;

    public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator)
    {
        this._navigationService = navigationService;
        this._eventAggregator = eventAggregator;
    }
}

image

Handling navigation between pages

To handle navigation between pages, Prism library offers to developer the interface INavigationAware (already implemented by the base ViewModel class). This interface exposes 2 methods:

  • OnNavigatedFrom: which is called before the navigation occurred. You can use this method to preserve the state of your data during the navigation
  • OnNavigatedTo: which is called after the navigation to a page is performed. This method can be used to retrieve parameter sent from a page to another page.

So this interface is really helpful if you want to execute navigation to another page within a component which has nothing to do with navigation (like a ViewModel for example!). And to change to another page, we’ll use the methods provided by the INavigationService (that is injected to the ViewModel’s constructor thanks to the dependency injection):

image

Saving properties’ values between the application’s states

As you know, a Windows Store application have different state: Not Running, Running, Suspended and Terminated. This is your job to preserve the properties’ value between the different states of your application so when users are going back to the application, they don’t feel there was a kind of pause (or termination) during the application’s execution.

So let’s take a look at the following example:

private string _mySuperString;

public string MySuperString
{
    get
    {
        return this._mySuperString;
    }
    set
    {
        this.SetProperty(ref this._mySuperString, value);
    }
}

And the dedicated XAML interface:

<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
            VerticalAlignment="Center">
    <TextBox HorizontalAlignment="Center"
             VerticalAlignment="Center"
             Text="{Binding MySuperString, Mode=TwoWay}" />
    <Button Content="Click Me!"
            HorizontalAlignment="Center"
            VerticalAlignment="Center" />
</StackPanel>

If I enter some text on the Textbox, the property will be updated in memory, thanks to the databinding feature. Each time the application is suspended and  terminated by the OS (which determined when to kill suspended apps to retrieve some resources), the text entered in the Textbox is deleted from the memory. To stop that, I can simply add the RestoreState attribute to the property:

private string _mySuperString;

[RestorableState]
public string MySuperString
{
    get
    {
        return this._mySuperString;
    }
    set
    {
        this.SetProperty(ref this._mySuperString, value);
    }
}

image

Now, I can execute the application and simulate a termination done by the OS, by using the Suspend and shutdown feature from the Debug Location toolbar:

image

If I execute the application again, without having to add other code, the MySuperString property will be automatically populated and the user interface will be modified:

image

Of course, you can also add more complex objects to the State to retrieve them later. For that, you’ll need to use the ISessionStateService (which exposes a Dictionary object) that manages the automatic load and save during application exit and startup!

First, to get the ISessionStateService object from your ViewModel, you need to get it injected to the constructor:

public MainPageViewModel(INavigationService navigationService, ISessionStateService sessionStateService)
{
    this._navigationService = navigationService;
    this._sessionStateService = sessionStateService;
}

Don’t forget to register the instance during the app’s initialization:

protected override void OnInitialize(IActivatedEventArgs args)
{
    _container.RegisterInstance<INavigationService>(NavigationService);
    _container.RegisterInstance<ISessionStateService>(SessionStateService);
}

Now, you just need to add your object to the session’s state:

public void SaveToSessionState()
    {
        var users = new List<User> { new User { Id = Guid.NewGuid(), Name = "Thomas LEBRUN" } };

        this._sessionStateService.SessionState.Add("DemoKey", users);
    }

public class User
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

And, finally, you can check (when the user navigated to the ViewModel) if the key exists in the dictionary:

public override void OnNavigatedTo(object navigationParameter, NavigationMode navigationMode, Dictionary<string, object> viewModelState)
{
    base.OnNavigatedTo(navigationParameter, navigationMode, viewModelState);

    if (_sessionStateService.SessionState.ContainsKey("DemoKey"))
    {
        var users = _sessionStateService.SessionState["DemoKey"] as List<User>;
        if (users != null)
        {
            //
        }
    }
}

Now, if you execute the code and simulate an termination of the app, you got a correct execution… or not :)

image

You’ll see that an exception is raised:

image

If you take a look at the details of the exception, you’ll see something familiar if you use to work with data serialization:

image

“Type ‘System.Collections.Generic.List`1[[DemoPrism.Views.Main.User, DemoPrism, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]’ with data contract name ‘ArrayOfUser:http://schemas.datacontract.org/2004/07/DemoPrism.Views.Main’ is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types – for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.”

Indeed, to save the session state, the system will serialize the items and here, we try to serialize a type (User) that is not known by the DataContractSerializer. So we need to teach it all about our custom type(s). This is done by overriding the method OnRegisterKnownTypesForSerialization of the MvvmAppBase class:

protected override void OnRegisterKnownTypesForSerialization()
{
    base.OnRegisterKnownTypesForSerialization();

    SessionStateService.RegisterKnownType(typeof(User));
    SessionStateService.RegisterKnownType(typeof(List<User>));
}

And now, the termination of the app works successfully and when the user navigated to the page, we can check/retrieve the results from the session state:

image

Simple but terribly useful isn’t it ?! Now, let’s see how we can communicate from a component to another one!

Communication between components using the Event Aggregator

Sometimes, you might need to communicate some data from a component to another one. This can be from ViewModelA to ViewModelB, ViewModelA to ViewC, ViewB to ViewA, etc. All this elements have one thing in common: they are not loosely coupled so there are no links between them. So how can we communicate from a component to another one when they are not linked ?

The answer is 2 words: Event Aggregator. This is a design pattern, also known as Publish/Subscribe, which is used to send a message (from the publisher) that is catched by all the subscribers (Martin Fowler talked about the pattern on his blog).

So how does it works ? Well, first, you need to get a reference to the Event Aggregator instance. This can be done through the dependency injection of the ViewModel’s constructor:

public MainPageViewModel(INavigationService navigationService, IEventAggregator eventAggregator, ISessionStateService sessionStateService)
{
    this._navigationService = navigationService;
    this._eventAggregator = eventAggregator;
    this._sessionStateService = sessionStateService;
}

Or thanks to Dependency Injection container you choose to use:

var eventAggregator = UnityServiceHelper.UnityContainer.Resolve<IEventAggregator>();

Then, we need to create the event object that will be sent from the publisher to the subscribers. This object is a simple class that inherits from the PubSubEvent<T> class:

public class SessionStateSavedEvent : PubSubEvent<object>
{
}

Now, we just have to publish an instance of this event. To do so, we’ll use the GetEvent method of the EventAggregator object and we’ll call the Publish method:

this._eventAggregator.GetEvent<SessionStateSavedEvent>().Publish(null);

This method takes in parameter the object you want to send to the subscribers (in our case, we don’t want to use any parameters so we send the null value). Finally, we need to add a handler that will be raised when the event will be catched by the subscriber:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    var eventAggregator = UnityServiceHelper.UnityContainer.Resolve<IEventAggregator>();
    eventAggregator.GetEvent<SessionStateSavedEvent>().Subscribe(OnSessionStateSavedEventSubscribe);
}

private void OnSessionStateSavedEventSubscribe(object obj)
{
    //
}

And voilà! Once the publisher send an instance of our event, all the subscribers will be notified and their handlers will be invoked:

image image

Of course, there are plenty other possibilities when using the Event Aggregator like specifying on which thread the handler will be executed or like filtering which handlers need to be executed:

image

image

 

Prism allows a lot of more (validation of user input, performance optimizations, etc.) but I hope this first overview gave you all you need to take a further look at this very cool library !

 

Happy coding!

 

PS: The source code of the article is available here.