XAML

Use the iOS system colors in Xamarin.Forms (Updated)

Use the iOS system colors in Xamarin.Forms (Updated)

Update

After publishing this post, Gerald Versluis from Microsoft responded on Twitter with an interesting information on how to get the system colors into our ResourceDictionary without using the DependencyService:

I had a quick look at the NamedPlatformColor class, but noticed that the implementation in Xamarin.Forms is incomplete. Gerald will try to update them. Once that is done, I will update the library on Github and this post again.

Original version below:


Overview

Let me give you a short overview first. To achieve our goal to use the iOS system colors, we need just a few easy steps:

  1. Xamarin.Forms interface that defines the colors
  2. Xamarin.iOS implementation of that interface
  3. ResourceDictionary to make the colors available in XAML
  4. Merging this dictionary with the application’s resource
  5. Handling of the OnRequestedThemeChanged event

Now that the plan is clear, let’s go into details.

ISystemColors interface

We will use the Xamarin.Forms DependencyService to get the colors from iOS to Xamarin.Forms. Let’s create our common interface:

using Xamarin.Forms;

namespace [YOURNAMESPACEHERE]
{
    public interface ISystemColors
    {
        Color SystemRed { get; }
        Color SystemOrange { get; }
        Color SystemYellow { get; }
        Color SystemGreen { get; }
        Color SystemMint { get; }
        Color SystemTeal { get; }
        Color SystemCyan { get; }
        Color SystemBlue { get; }
        Color SystemIndigo { get; }
        Color SystemPurple { get; }
        Color SystemPink { get; }
        Color SystemBrown { get; }
        Color SystemGray { get; }
        Color SystemGray2 { get; }
        Color SystemGray3 { get; }
        Color SystemGray4 { get; }
        Color SystemGray5 { get; }
        Color SystemGray6 { get; }
        Color SystemLabel { get; }
        Color SecondaryLabel { get; }
        Color TertiaryLabel { get; }
        Color QuaternaryLabel { get; }
        Color Placeholder { get; }
        Color Separator { get; }
        Color OpaqueSeparator { get; }
        Color LinkColor { get; }
        Color FillColor { get; }
        Color SecondaryFillColor { get; }
        Color TertiaryFillColor { get; }
        Color QuaternaryFillColor { get; }
        Color SystemBackgroundColor { get; }
        Color SecondarySystemBackgroundColor { get; }
        Color TertiarySystemBackgroundColor { get; }
        Color SystemGroupedBackgroundColor { get; }
        Color SecondarySystemGroupedBackgroundColor { get; }
        Color TertiarySystemGroupedBackgroundColor { get; }
        Color DarkTextColor { get; }
        Color LightTextColor { get; }
    }
}

As we are not able to change any of the system colors, we are just defining getters in the interface.

The Xamarin.iOS platform implementation

The implementation is straight forward. We are implementing the interface and just get the values for each system color. The list is based on Apple’s documentation for human interface and UI element colors.

using [YOURNAMESPACEHERE];

using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: Dependency(typeof(SystemColors))]
namespace [YOURNAMESPACEHERE]
{
    //https://developer.apple.com/design/human-interface-guidelines/ios/visual-design/color/
    //https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors

    public class SystemColors : ISystemColors
    {
        #region System Colors
        public Color SystemRed => UIColor.SystemRedColor.ToColor();
        public Color SystemOrange => UIColor.SystemOrangeColor.ToColor();
        public Color SystemYellow => UIColor.SystemYellowColor.ToColor();
        public Color SystemGreen => UIColor.SystemGreenColor.ToColor();
        public Color SystemMint => UIColor.SystemMintColor.ToColor();
        public Color SystemTeal => UIColor.SystemTealColor.ToColor();
        public Color SystemCyan => UIColor.SystemCyanColor.ToColor();
        public Color SystemBlue => UIColor.SystemBlueColor.ToColor();
        public Color SystemIndigo => UIColor.SystemIndigoColor.ToColor();
        public Color SystemPurple => UIColor.SystemPurpleColor.ToColor();
        public Color SystemPink => UIColor.SystemPinkColor.ToColor();
        public Color SystemBrown => UIColor.SystemBrownColor.ToColor();


        public Color SystemGray => UIColor.SystemGrayColor.ToColor();
        public Color SystemGray2 => UIColor.SystemGray2Color.ToColor();
        public Color SystemGray3 => UIColor.SystemGray3Color.ToColor();
        public Color SystemGray4 => UIColor.SystemGray4Color.ToColor();
        public Color SystemGray5 => UIColor.SystemGray5Color.ToColor();
        public Color SystemGray6 => UIColor.SystemGray6Color.ToColor();
        #endregion

        #region UI Element Colors
        public Color SystemLabel => UIColor.LabelColor.ToColor();
        public Color SecondaryLabel => UIColor.SecondaryLabelColor.ToColor();
        public Color TertiaryLabel => UIColor.TertiaryLabelColor.ToColor();
        public Color QuaternaryLabel => UIColor.QuaternaryLabelColor.ToColor();
        public Color Placeholder => UIColor.PlaceholderTextColor.ToColor();
        public Color Separator => UIColor.SeparatorColor.ToColor();
        public Color OpaqueSeparator => UIColor.SeparatorColor.ToColor();
        public Color LinkColor => UIColor.SeparatorColor.ToColor();

        public Color FillColor => UIColor.SystemFillColor.ToColor();
        public Color SecondaryFillColor => UIColor.SecondarySystemFillColor.ToColor();
        public Color TertiaryFillColor => UIColor.TertiarySystemFillColor.ToColor();
        public Color QuaternaryFillColor => UIColor.QuaternarySystemFillColor.ToColor();

        public Color SystemBackgroundColor => UIColor.SystemBackgroundColor.ToColor();
        public Color SecondarySystemBackgroundColor => UIColor.SecondarySystemBackgroundColor.ToColor();
        public Color TertiarySystemBackgroundColor => UIColor.TertiarySystemBackgroundColor.ToColor();

        public Color SystemGroupedBackgroundColor => UIColor.SystemGroupedBackgroundColor.ToColor();
        public Color SecondarySystemGroupedBackgroundColor => UIColor.SecondarySystemGroupedBackgroundColor.ToColor();
        public Color TertiarySystemGroupedBackgroundColor => UIColor.TertiarySystemGroupedBackgroundColor.ToColor();

        public Color DarkTextColor => UIColor.DarkTextColor.ToColor();
        public Color LightTextColor => UIColor.LightTextColor.ToColor();

        #endregion
    }
}

Do not forget to add the Dependency attribute on top of the implementation, otherwise it won’t work.

The ResourceDictionary

As I prefer defining my UI in XAML in Xamarin.Forms, I naturally want those colors to be available there as well. This can be done by loading the colors into a ResourceDictionary. As you might remember, I prefer codeless ResourceDictionary implementations. This time, however, we need the code-behind file to make the ResourceDictionary work for us.

First, add a new ResourceDictionary:

Add_ResourceDictionary_XAML

Then, in the code-behind file, we are using the DependencyService of Xamarin.Forms to add the colors to the ResourceDictionary:

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace [YOURNAMESPACEHERE]
{
    public partial class SystemColorsIosResourceDictionary
    {
        public SystemColorsIosResourceDictionary()
        {
            InitializeComponent();

            this.Add(nameof(ISystemColors.SystemRed), DependencyService.Get<ISystemColors>().SystemRed);
            this.Add(nameof(ISystemColors.SystemOrange), DependencyService.Get<ISystemColors>().SystemOrange);
            this.Add(nameof(ISystemColors.SystemYellow), DependencyService.Get<ISystemColors>().SystemYellow);
            this.Add(nameof(ISystemColors.SystemGreen), DependencyService.Get<ISystemColors>().SystemGreen);
            this.Add(nameof(ISystemColors.SystemMint), DependencyService.Get<ISystemColors>().SystemMint);
            this.Add(nameof(ISystemColors.SystemTeal), DependencyService.Get<ISystemColors>().SystemTeal);
            this.Add(nameof(ISystemColors.SystemCyan), DependencyService.Get<ISystemColors>().SystemCyan);
            this.Add(nameof(ISystemColors.SystemBlue), DependencyService.Get<ISystemColors>().SystemBlue);
            this.Add(nameof(ISystemColors.SystemIndigo), DependencyService.Get<ISystemColors>().SystemIndigo);
            this.Add(nameof(ISystemColors.SystemPurple), DependencyService.Get<ISystemColors>().SystemPurple);
            this.Add(nameof(ISystemColors.SystemPink), DependencyService.Get<ISystemColors>().SystemPink);
            this.Add(nameof(ISystemColors.SystemBrown), DependencyService.Get<ISystemColors>().SystemBrown);


            this.Add(nameof(ISystemColors.SystemGray), DependencyService.Get<ISystemColors>().SystemGray);
            this.Add(nameof(ISystemColors.SystemGray2), DependencyService.Get<ISystemColors>().SystemGray2);
            this.Add(nameof(ISystemColors.SystemGray3), DependencyService.Get<ISystemColors>().SystemGray3);
            this.Add(nameof(ISystemColors.SystemGray4), DependencyService.Get<ISystemColors>().SystemGray4);
            this.Add(nameof(ISystemColors.SystemGray5), DependencyService.Get<ISystemColors>().SystemGray5);
            this.Add(nameof(ISystemColors.SystemGray6), DependencyService.Get<ISystemColors>().SystemGray6);

            this.Add(nameof(ISystemColors.SystemLabel), DependencyService.Get<ISystemColors>().SystemLabel);
            this.Add(nameof(ISystemColors.SecondaryLabel), DependencyService.Get<ISystemColors>().SecondaryLabel);
            this.Add(nameof(ISystemColors.TertiaryLabel), DependencyService.Get<ISystemColors>().TertiaryLabel);
            this.Add(nameof(ISystemColors.QuaternaryLabel), DependencyService.Get<ISystemColors>().QuaternaryLabel);

            this.Add(nameof(ISystemColors.Placeholder), DependencyService.Get<ISystemColors>().Placeholder);
            this.Add(nameof(ISystemColors.Separator), DependencyService.Get<ISystemColors>().Separator);
            this.Add(nameof(ISystemColors.OpaqueSeparator), DependencyService.Get<ISystemColors>().OpaqueSeparator);
            this.Add(nameof(ISystemColors.LinkColor), DependencyService.Get<ISystemColors>().LinkColor);

            this.Add(nameof(ISystemColors.FillColor), DependencyService.Get<ISystemColors>().FillColor);
            this.Add(nameof(ISystemColors.SecondaryFillColor), DependencyService.Get<ISystemColors>().SecondaryFillColor);
            this.Add(nameof(ISystemColors.TertiaryFillColor), DependencyService.Get<ISystemColors>().TertiaryFillColor);
            this.Add(nameof(ISystemColors.QuaternaryFillColor), DependencyService.Get<ISystemColors>().QuaternaryFillColor);

            this.Add(nameof(ISystemColors.SystemBackgroundColor), DependencyService.Get<ISystemColors>().SystemBackgroundColor);
            this.Add(nameof(ISystemColors.SecondarySystemBackgroundColor), DependencyService.Get<ISystemColors>().SecondarySystemBackgroundColor);
            this.Add(nameof(ISystemColors.TertiarySystemBackgroundColor), DependencyService.Get<ISystemColors>().TertiarySystemBackgroundColor);

            this.Add(nameof(ISystemColors.SystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().SystemGroupedBackgroundColor);
            this.Add(nameof(ISystemColors.SecondarySystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().SecondarySystemGroupedBackgroundColor);
            this.Add(nameof(ISystemColors.TertiarySystemGroupedBackgroundColor), DependencyService.Get<ISystemColors>().TertiarySystemGroupedBackgroundColor);

            this.Add(nameof(ISystemColors.DarkTextColor), DependencyService.Get<ISystemColors>().DarkTextColor);
            this.Add(nameof(ISystemColors.LightTextColor), DependencyService.Get<ISystemColors>().LightTextColor);

        }
    }
}

That’s all for the implementation. Now let’s start having a look at how to use the whole code we wrote until now.

Merging the ResourceDictionary

In Xamarin.Forms, we are able to merge ResourceDictionary classes to make them available for the whole app or on view/page level only. I consider our above created dictionary as an app-level dictionary. On top, to make it reusable, I put all these classes in a separate multi-platform library, which you can find here on Github.

Please note that the syntax will be a little different if you implement the ResourceDictionary directly in your app. Using the library approach, you will merge the dictionary in this way in App.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<Application
    x:Class="SystemColorsTest.App"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:systemcolors="clr-namespace:MSiccDev.Libs.iOS.SystemColors;assembly=MSiccDev.Libs.iOS.SystemColors">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <systemcolors:SystemColorsIosResourceDictionary />
                <!--  more dictionaries here  -->
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

Responding to system theme changes

Even if I personally only change the system theme at runtime for testing themes in my apps, your users may do so frequently. Luckily, it is just a matter of handling an event to handle this scenario. In your App.xaml.cs file, register for the RequestedThemeChanged event within the constructor:

        public App()
        {
            InitializeComponent();

            Application.Current.RequestedThemeChanged += OnRequestedThemeChanged;

            this.MainVm = new MainViewModel();
            MainPage mainPage = new MainPage()
            {
                BindingContext = this.MainVm
            };

            MainPage = mainPage;
        }

As the system colors respond to the system theme change, we need to reload them to get these changes.

Within the OnRequestedThemeChanged method, we are first getting the actual merged ResourceDictionary instance. Then, we will remove this instance and register a new instance of the ResourceDictionary. This will lead to a full reload of the system colors from iOS into the app. Here is the code:

private void OnRequestedThemeChanged(object sender, AppThemeChangedEventArgs e)
{
    ResourceDictionary iosResourceDict = App.Current.Resources.MergedDictionaries.SingleOrDefault(dict => dict.GetType() == typeof(SystemColorsIosResourceDictionary));

    if (iosResourceDict != null)
    {
        App.Current.Resources.MergedDictionaries.Remove(iosResourceDict);
        App.Current.Resources.MergedDictionaries.Add(new SystemColorsIosResourceDictionary());
    }
}

That’s it, we are now ready to use the colors in XAML and our app adapts to system theme changes. Here is a sample XAML which I wrote to test the colors:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage
    x:Class="SystemColorsTest.MainPage"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:SystemColorsTest"
    x:DataType="local:MainViewModel"
    BackgroundColor="{DynamicResource SystemBackgroundColor}">

    <StackLayout>
        <Frame
            Padding="12,42,24,12"
            BackgroundColor="{DynamicResource SystemGray3}"
            CornerRadius="0">
            <Label
                FontSize="36"
                HorizontalTextAlignment="Center"
                Text="iOS SystemColors in XF"
                TextColor="{AppThemeBinding Dark={DynamicResource LightTextColor},
                                            Light={DynamicResource DarkTextColor}}" />
        </Frame>

        <ScrollView>
            <StackLayout BindableLayout.ItemsSource="{Binding SystemColors}">
                <BindableLayout.ItemTemplate>
                    <DataTemplate>
                        <Frame
                            Margin="6,3"
                            x:DataType="local:SystemColorViewModel"
                            BackgroundColor="{Binding Value}">
                            <Label Text="{Binding Name}" />
                        </Frame>
                    </DataTemplate>
                </BindableLayout.ItemTemplate>
            </StackLayout>
        </ScrollView>
    </StackLayout>
</ContentPage>

Please note that I use DynamicResource instead of StaticResource, even if some colors are static. Using DynamicResource forces the app to reload the colors, and there are some that change (like the SystemGray color palette).

Conclusion

Using the iOS system colors in Xamarin.Forms isn’t that complicated with this implementation. If you have more platforms, you could implement the same technique for the other platforms. As I am focusing on iOS for the moment, I just wrote that part. But who knows, maybe this will be extended in the future.

As always, I hope this post will be helpful for some of you.

Until the next post, happy coding, everyone!

Posted by msicc in Dev Stories, iOS, Xamarin, 5 comments
#XFQaD: Compile XAML without code behind in Xamarin.Forms

#XFQaD: Compile XAML without code behind in Xamarin.Forms

How I discovered this #XFQaD

When I was reorganizing the application resources on my current side project, I decided to create some thematically divided ResourceDictionary files. This has led me to do a quick research on Xamarin.Forms resource dictionaries.

If you’re doing this research, you will stumble upon this post from 2018 (!), where the hint to the magic I’ll show you soon was hidden.

Until now, I only used this with ResourceDictionary files. Maybe it will be helpful also for other XAML resources like controls (I will try that in the future).

How to make XAML only files compile

Add a new XAML file (sample is still ResourceDictionary) to your project:

Add_ResourceDictionary

Delete the code behind file, and add your XAML code. Before hitting the Build button, add this line immediately after the .xml file header:

<?xaml-comp compile="true" ?>

This line is where the magic happens. It tells the compiler to include the XAML file in the Build, pretty much like it does with XAML compile attribute in the code behind file.

Conclusion

The only place where I found this hint was the blog post mentioned above. Neither the docs on XAML Compilation nor the docs on resource dictionaries are mentioning this trick. It somehow went quietly from the nightly builds into production code.

Using this trick, we are able to have a more clean project structure. As always, I hope this post will be helpful for some of you.

Until the next post, happy coding!

Posted by msicc in Dev Stories, 9 comments
Visual Studio Extensions that will make your life easier in 2020

Visual Studio Extensions that will make your life easier in 2020

Xaml Styler

Download Link: https://marketplace.visualstudio.com/items?itemName=TeamXavalon.XAMLStyler

Project Site: https://github.com/Xavalon/XamlStyler

In Visual Studio 2019, writing XAML normally ends up in very long lines because it does not automatically break into new lines. In May 2019, I discovered the Xaml Styler extension by watching a video on Channel9.

Xaml Styler, even in its default configuration (which I did never change, tbh), breaks your XAML code into new lines once the count of properties of an element exceeds a certain amount. The extension as tons of options to configure, but for me, the default config always worked well.

Here is a sample:

As you can see, the XAML file is a by far more readable now. The different colors on the namespace declarations and closing tags are coming from the next extension on my list.

Viasfora

Download Link: https://marketplace.visualstudio.com/items?itemName=TomasRestrepo.Viasfora

Project Site: https://viasfora.com/

Viasfora aims to make your code more readable. To achieve that goal, it is coloring the code inside Visual Studio. The coloring makes it easy to see the scopes of each line, method, and even classes. As I discovered the extensions only a few weeks ago, I decided to not change any of the default settings, but it is already making my code a whole lot more readable.

Here is a sample from one of my recent projects:

VSColorOutput

Download Link: https://marketplace.visualstudio.com/items?itemName=MikeWard-AnnArbor.VSColorOutput

Project Site: https://mike-ward.net/vscoloroutput/

Ever tried to search the Visual Studio output for warnings, build errors or exceptions? Of course, you did. VSColorOutput makes this search a whole lot easier, as it colors errors/exceptions in red, warning in yellow, and build success messages in green. You see everything at a glance, which can save you a lot of time. See yourself:

CodeMaid

Download Link: https://marketplace.visualstudio.com/items?itemName=SteveCadwallader.CodeMaid

Project Site: http://www.codemaid.net/

CodeMaid is a very powerful extension. I am pretty sure I am not even using half of its functions, to be honest. I mainly use it to let it automatically sort my code files to my gusto and let it generate regions around it. This way, my code stays always organized in the same way and I don’t even have to think about it. I will explore more of the other functions moving onwards.

Here is a sample of a code file after CodeMaid cleaned it up (collapsed regions):

Material icons generator

Download Link: https://marketplace.visualstudio.com/items?itemName=nikainteristi.Materialiconsgenerator

Project Site: https://github.com/interisti/vs-material-icons-generator

If you are developing mobile applications, chances are high you will need one or another icon within an app. Material icons generator tries to replicate the popular function of Android Studio, with the added bonus of making it also available for iOS and UWP apps. The extension sadly does not create Image Asset folders and .json files for iOS correctly, but it creates the images so one can create an Image Asset from it in just a minute. The project does seem to be actively developed according to Github – I put this extension on the list because I did not find a better alternative until now.

Markdown Editor

Download Link: https://marketplace.visualstudio.com/items?itemName=MadsKristensen.MarkdownEditor

Project Site: https://github.com/madskristensen/MarkdownEditor

If you have to deal with Markdown files, there are floating quite a few helper apps around the web. I prefer to work on them in Visual Studio, as I use Markdown most of the time on Github when writing readme or similar files. Markdown Editor makes it easy to do so, and I almost immediately see the result in the preview window, which is quite helpful from time to time.

The extension is written by the creator of Markdig, which is by far your best option if you have to deal with Markdown in your C# app. Here is a sample:

Regex Editor

Download Link: https://marketplace.visualstudio.com/items?itemName=GeorgyLosenkov.RegexEditorLite

Project Site: N/A

If you ever had to deal with validations, chances are high you solved it with Regex. The extension provides a bunch of options that will help you to write Regex-patterns. You can test it in the same Window with some sample data to verify it will do what it is supposed to do. As a bonus, it is able to create a sample method of how to use it if you want to. Here is what it looks like with an email verification pattern:

Conclusion

To kick off my blogging year 2020, I showed you some of the most helpful Visual Studio extensions I installed on my machine. I hope some of you will find the one or another extension as helpful as I do. If you have an extension that is not on my list and you consider it useful, feel free to sound off in the comments or via social media.

Until the next post, happy coding!

Posted by msicc in Dev Stories, 4 comments
[Updated] A workaround for Xamarin Forms 2.5 bug that prevents resource declaration in App.xaml

[Updated] A workaround for Xamarin Forms 2.5 bug that prevents resource declaration in App.xaml

Update: Xamarin appearently solved this problem with Service Release 3 for Xamarin Forms 2.5. I can confirm it works in the app that caused me to write this post.

Additional note: the forms:prefix is no longer needed, just insert the <ResourceDictionary>tag.


If you have a Windows background like I do, one of the most normal things for applications is to create keyed Resources in App.xaml to make them available throughout the app. Something like this should look familiar:

<forms:ResourceDictionary >
    <viewModels:ViewModelLocator x:Key="Locator"></viewModels:ViewModelLocator>
    <forms:Color x:Key="MainAccentColor">#1e73be</forms:Color>
    <forms:Color x:Key="LightAccentColor">#61a1f1</forms:Color>
    <forms:Color x:Key="DarkAccentColor">#00488d</forms:Color>
    <forms:Color x:Key="MainBackgroundColor">#f4f4f4</forms:Color>
</forms:ResourceDictionary>

This is also possible in Xamarin.Forms. Sadly, Xamarin.Forms 2.5 introduced an ugly bug where this declarations throw an ArgumentException, telling us the key(s) already exist in the dictionary (see Bugzilla here). I can confirm that this bug affects at least UWP, Android and iOS applications which use such an implementation.

As this is a show-stopping bug, I had to find a way to work around it for the moment. In such cases, I always try to find a way that has only very little impact. For this particular bug, I just moved the declaration of the resources into the code-behind file, which keeps the rest of my code unchanged. I just created a method that does the work I originally had in the .xaml-file:

//needed because of Xamarin Bug  https://bugzilla.xamarin.com/show_bug.cgi?id=60788
private void CreateResourceDictionary()
{
    //making sure there is only one dictionary
    if (this.Resources == null)
        this.Resources = new ResourceDictionary();

    //making sure there is only one key
    if (!this.Resources.ContainsKey("Locator"))
    {
        this.Resources.Add("Locator", ViewModels.ViewModelLocator.Instance);
    }

    if (!this.Resources.ContainsKey("MainAccentColor"))
    {
        this.Resources.Add("MainAccentColor", Color.FromHex("#1e73be"));
    }

    if (!this.Resources.ContainsKey("LightAccentColor"))
    {
        this.Resources.Add("LightAccentColor", Color.FromHex("#61a1f1"));
    }

    if (!this.Resources.ContainsKey("DarkAccentColor"))
    {
        this.Resources.Add("DarkAccentColor", Color.FromHex("#00488d"));
    }

    if (!this.Resources.ContainsKey("MainBackgroundColor"))
    {
        this.Resources.Add("MainBackgroundColor", Color.FromHex("#f4f4f4"));
    }
}

This makes the application running again like it did before. Once the bug in Xamarin.Forms is fixed, I just have to delete this method and uncomment the XAML-declarations to get back to the state where I was prior to Xamarin.Forms 2.5.

If you are experiencing the same bug, I recommend to also comment on the Bugzilla-Entry (link).

As always, I hope this post is helpful for some of you.

Happy coding!

 

 

Posted by msicc in Android, Dev Stories, iOS, UWP, Xamarin, 4 comments
Xamarin Forms, the MVVMLight Toolkit and I: EventToCommandBehavior

Xamarin Forms, the MVVMLight Toolkit and I: EventToCommandBehavior

Often, we want to/need to know when views throw certain events. However, due to using the MVVM pattern, our application logic is separated from the view. There are several ways to get those events into our ViewModel while keeping it separated from the views. One of those is using an interface, which I showed you already in my blog post about navigation in Xamarin.Forms with MVVMLight.

Another way is the good old EventToCommand approach. Some of you might have used this approach already in WPF and other .NET applications. Xamarin.Forms has them too, this post will show you how to implement it.

Xamarin.Forms Behaviors

In Windows applications like WPF or UWP, we normally use the Interactivity namespace to use behaviors. Xamarin.Forms however has its own implementation, so we need to use the Behavior and Behavior<T> classes. All controls that derive from View are providing this BindableProperty, so we can use Behaviors in a lot of scenarios. Until the new XAML Standard is finally defined, we have to deal with this.

EventToCommandBehavior

Xamarin provides a nearly ready-to-use EventToCommandBehavior implementation and an quite detailed explanation (which is why I won’t go into details on that). The implementation has two part – the BehaviorBase<T>implementation and the EventToCommandBehavior implementation itself.

While we are able to use the BehaviorBase<T> implementation as is, we have to do some minor changes to the EventToCommandBehavior to enable a few more usage scenarios.

The first change we need to make is to derive Xamarin’s EventToCommandBehavior sample from VisualElement instead of View. This way, we can also use the behavior on controls that do not derive from View, especially in Pages. Pages do not derive from View, but they do from VisualElement (like Viewdoes, too). You need to change the Type also on the parameter of the OnAttachedTo and OnDetachingFrom methods in this case (which are the other two changes we need to do).

The rest of the implementation is basically the same like in the Xamarin sample and works quite well.

To show you a simple sample in Action, we are using the Appearing and Disappearing events to attach them via the behavior into our ModalPageViewModelon the ModalPage we integrated before. This way, you won’t need the IViewEventBrokerService I showed you in my post on navigation and modal pages. It is up to you to choose the way you want to go along, both ways are fully respecting the MVVM pattern.

Implementation

The implementation has two parts. As we want to handle the events in a Command, the first step to take is to implement two Commands in the corresponding ViewModel. I am using a base implementation (in my apps and also in this sample), so I am going to implement the Commands there. This way, every derived ViewModel can bind to this Command. Additionally, I am using a Execute...Command method and a CanExecute boolean method, which can both be overriden in derived ViewModels to implement the code to execute. Let’s have a look at the code:

public RelayCommand ViewAppearingCommand => _viewAppearingCommand ?? (_viewAppearingCommand = new RelayCommand(ExecuteViewAppearingCommand, CanExecuteViewAppearingCommand));

public virtual void ExecuteViewAppearingCommand()
{

}

public virtual bool CanExecuteViewAppearingCommand()
{
    return true;
}

public RelayCommand ViewDisappearingCommand => _viewDisappearingCommand ?? (_viewDisappearingCommand = new RelayCommand(ExecuteViewDisappearingCommand, CanExecuteViewDisappearingCommand));

public virtual void ExecuteViewDisappearingCommand()
{

}

public virtual bool CanExecuteViewDisappearingCommand()
{
    return true;
}

The second part is the XAML part, which includes the Binding to the Command properties we just created. The implementation is as easy as these four lines for both events:

    <baseCtrl:XfNavContentPage.Behaviors>
        <behaviors:EventToCommandBehavior EventName="Appearing" Command="{Binding ViewAppearingCommand}"></behaviors:EventToCommandBehavior>
        <behaviors:EventToCommandBehavior EventName="Disappearing" Command="{Binding ViewDisappearingCommand}"></behaviors:EventToCommandBehavior>
    </baseCtrl:XfNavContentPage.Behaviors>

That’s it, if you want to attach the behavior only for individual Pages. If you have a base page implementation like I do however, you can automatically attach the event already there to have it attached to all pages:

private void XfNavContentPage_BindingContextChanged(object sender, EventArgs e)
{
    if (this.BindingContext is XfNavViewModelBase)
    {
        this.Behaviors.Add(new EventToCommandBehavior()
        {
            EventName = "Appearing",
            Command = ((XfNavViewModelBase)this.BindingContext).ViewAppearingCommand
        });
 
        this.Behaviors.Add(new EventToCommandBehavior()
        {
            EventName = "Disappearing",
            Command = ((XfNavViewModelBase)this.BindingContext).ViewDisappearingCommand
        });
    }
}

I am attaching the behaviors only if the BindingContextdoes derive from my XfNavViewModelBase. The Command can be set directly in this case, without the need to use the SetBinding method.

These few lines are connecting the Event to the Command, the only thing we need to do is to override the base implementations of the “Execute…Command” methods:

public override async void ExecuteViewAppearingCommand()
{
    base.ExecuteViewAppearingCommand();
    await _dialogService.ShowMessageAsync(this.CorrespondingViewKey, $"from overriden {nameof(ExecuteViewAppearingCommand)}");
}
 
public override async void ExecuteViewDisappearingCommand()
{
    base.ExecuteViewDisappearingCommand();
    await _dialogService.ShowMessageAsync(this.CorrespondingViewKey, $"from overriden {nameof(ExecuteViewDisappearingCommand)}");
}

The above overrides are using the IDialogService you will find in the sample application to show a simple message from which overriden Execute...Command method they are created from.

Converting EventArgs to specific types

Xamarin.Forms has only a few events that have usefull EventArgs. At the time of writing this post, I tried to find valid scenarios where we want to get some things of the events to attach also an IValueConverterimplementation to get this data out of them. Fact is, the only one I ever used is the one from the Xamarin sample – which is a converter that gets the selected Item for a ListView. Because Xamarin.Forms Views already provide most of the properties I ever needed, I was able to solve everything else via Binding. To make this post complete, you can have a look into Xamarin’s sample implementation here.

Conclusion

Hooking into events on the view side of our applications can be done in several ways. It is up to you to choose the route you want to go. With this post, I showed you a second way to achieve this.

If you have some more valid scenarios for using the EventToCommandBehaviorwith a Converter that cannot be solved via Binding directly, I would love to hear them. Feel free to leave a comment here or via social networks. Of course, I updated the sample on Github with the code from this post.

As always, I hope this post is helpful for some of you. Until the next post, happy coding!

Posted by msicc in Android, Dev Stories, iOS, UWP, Xamarin, 3 comments

[Updated] How to create a pure icon button for your UWP app

[Updated: the first version of this blog post was using a UserControl. Thanks to a discussion on Twitter, I realized that wrapping it into a UserControl is overblown (yes, sometimes I tend to write more code than necessary). This is the updated version using only a Style for the button.]

When writing apps, you often come along a point where you want to style controls differently than the original style. Today, I‘ll show you a pure icon button that does not show the surrounding shape and borders. Instead, it highlights the icon of the button when hovering over it, while it changes the color to the user’s accent color when it gets pressed. Here is a little animation of what I am talking about:cromeless button demo

It all begins with the default style of the Button control, which you can see here. We are going to modify this Style until it matches the above animation. The first thing we change is the BackgroundBrush – set it to ‘Transparent’ to get rid of the grey shape that the button control comes with when hovering over it or pressing it:

<Setter Property="Background" Value="Transparent"/>

As we want an icon button, we need to choose a common source for the icons as well. I am using a Path Shape as the icon source, as it allows modifications to be done in XAML. So the next step is to add a Path shape to the Style:

                            <Path x:Name="PathIcon"
                                  Data="{TemplateBinding Content}"
                                  Stretch="Uniform"
                                  Fill="{TemplateBinding Foreground}"
                                  Stroke="Transparent"
                                  StrokeThickness="1"
                                  Margin="4"
                                  RenderTransformOrigin="0.5,0.5">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <TransformGroup.Children>
                                            <RotateTransform Angle="0" />
                                            <ScaleTransform ScaleX="1" ScaleY="1" />
                                        </TransformGroup.Children>
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>

In this case, as we just want to use the icon within our button, we can safely remove the ‘ContentPresenter’ part in the Style. We have made quite some progress already, but that all does not make the control behaving like in the animation yet.

Now it is the time to modify the CommonStates of the Button’s style. Our Button uses only an icon, so we need to add the color states for the Path’s ‘Fill (=Foreground)’ to the states. Here are the modifications:

‘PointerOver’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>

‘Pressed’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundAccentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>

‘Disabled’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>

To get the icon’s outline highlighting, we are going to use the Path’s ‘Stroke (=Border)’ property. Add these modifications to the Style in XAML:

‘PointerOver’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>

‘Pressed’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>

‘Disabled’ state:

                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>

All that is left is to use the Style on any desired button:

    <Button x:Name="BaseButton" Style="{StaticResource TransparentButtonStyle}"></Button>

If you now use this one in an application, you will get the same result as in the initial animation.

For easier use, here is the complete code:

        <Style x:Key="TransparentPathIconButtonStyle" TargetType="Button">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
            <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}"/>
            <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
            <Setter Property="Padding" Value="8,4,8,4"/>
            <Setter Property="HorizontalAlignment" Value="Stretch"/>
            <Setter Property="VerticalAlignment" Value="Stretch"/>
            <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
            <Setter Property="FontWeight" Value="Normal"/>
            <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
            <Setter Property="UseSystemFocusVisuals" Value="True"/>

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal">
                                        <Storyboard>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="PointerOver">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAccentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Pressed">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlForegroundAccentBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="Disabled">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Fill" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseMediumLowBrush}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Stroke" Storyboard.TargetName="PathIcon">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>

                            <Path x:Name="PathIcon"
                                  Data="{TemplateBinding Content}"
                                  Stretch="Uniform"
                                  Fill="{TemplateBinding Foreground}"
                                  Stroke="Transparent"
                                  StrokeThickness="1"
                                  Margin="4"
                                  RenderTransformOrigin="0.5,0.5">
                                <Path.RenderTransform>
                                    <TransformGroup>
                                        <TransformGroup.Children>
                                            <RotateTransform Angle="0" />
                                            <ScaleTransform ScaleX="1" ScaleY="1" />
                                        </TransformGroup.Children>
                                    </TransformGroup>
                                </Path.RenderTransform>
                            </Path>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

As always, I hope this post is helpful for some of you. If you have questions/ideas for improvements or just want to talk about the control, feel free to leave a comment below.

Happy Coding, everyone!

Posted by msicc in Dev Stories, UWP, 3 comments

My experiences with Xamarin.Forms

Xamarin-logo-hexagon-blue

As I have finished my first iOS app with Xamarin.Forms, I want to share my experience that I made during writing it.

It sounds great. Build the code once, run it on Android, iOS and Windows Phone (8). Xamarin is using the well known PCL to achieve this goal, or a shared asset project.

As I am familiar with the PCL structure, I decided to go with this one. The application I wrote for Telefónica had already their Windows Phone and Android counterpart. My thought was to bring together all three after finishing the iOS app into the Xamarin.Forms project to make it easier to maintain them (that was before it was clear that I would leave, but that’s another story). In the end, I focused on the iOS platform and implementation, leaving the other two out.

It was far easier to start a new iOS app with Xamarin.Forms than in the traditional way. Although there are some XAML gotchas (like Nicolò wrote already on his blog), it is pretty easy to get started with it.

The number one tip I can give you is to wrap everything in a principal Grid and set you ColumnWidth (also if you have only one single Column). This will help you to better position your controls on the page.

One really annoying thing is the missing IntelliSense support when you’re writing your XAML code. What does that mean? It means your will spend a lot of time with trial and error as well as reading the documentation in the beginning.

One thing that is solved in a good way is the access to native functions that are not implemented in the Forms project. Connecting through interfaces and Xamarin’s DependencyService, you can write the implementation you need in the native project and call the function from the Forms PCL. I will cover this in another blog post.

Often, you want/need your app to be designed in a different way (like I had to for Telefónica). Some basic modifications are possible from the XAML part. But the most effective way to achieve this goal for the whole app is to use Custom Renderer. This will be another post’s topic in the coming days.

Overall, Xamarin.Forms is already impressive. But you need to know that you will work with some workarounds when you start. If you are willing to do this, you might be able write a cross platform app in little time.

If you do not want to dig into the documentation or use the techniques I wrote about, Xamarin.Forms might not yet be your starting point for your cross platform app.

One last tip: To make it easier for you, there is the Xamarin.Forms Lab project. This community project has already extended Xamarin.Forms, and is worth a look and a second thought if you truly want to do a cross platform app with Xamarin.

Happy coding, everyone!

Posted by msicc in Dev Stories, Xamarin, 2 comments

How to capture a photo in your Windows Phone 8.1 Runtime app – Part III: capturing and saving the photo

This is the third and last post of this series. In the first two posts I showed you how to start the preview of MediaCapture and some modifications we can apply to it. In this post, we are finally capturing and saving the photo – including the modifications we made before.

The easiest way – capture as is:

The easiest way to capture the photo is to use MediaCapture’s CapturePhotoToStorageFileAsync() method. This method shows you how to do it:

            //declare image format
            ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();

            //generate file in local folder:
            StorageFile capturefile = await ApplicationData.Current.LocalFolder.CreateFileAsync("photo_" + DateTime.Now.Ticks.ToString(), CreationCollisionOption.ReplaceExisting);

            ////take & save photo
            await captureManager.CapturePhotoToStorageFileAsync(format, capturefile);

            //show captured photo
            BitmapImage img = new BitmapImage(new Uri(capturefile.Path));
            takenImage.Source = img;
            takenImage.Visibility = Visibility.Visible;

This way however does not respect any modifications we made to the preview. The only thing that gets respected is the camera device we are using.

Respecting rotation in the captured photo:

In our ongoing sample, we are using a 90 degree rotation to display the preview element in portrait mode. Naturally, we want to port over this orientation in our captured image.

There are two ways to achieve this. We could capture the photo to a WriteableBitmap and manipulate it, or we could manipulate the image stream directly with the BitmapDecoder and  BitmapEncoder classes. We will do the latter one.

First, we need to open an InMemoryRandomAccessStream for our the captured photo. We are capturing the photo to the stream with MediaCapture’s CapturePhotoToStreamAsync() method, specifing the stream name and the image format.

The next step is to decode the stream with our BitmapDecoder. If we are performing only rotation, we can directly re-encode the InMemoryRandomAccessStream we are using. Rotating the captured photo is very simple with just setting the BitmapTransform.Rotation property to be rotated by 90 degrees, pretty much as easy as rotating the preview.

The last steps are generating a file in the storage, followed by copying the transcoded image stream into the file stream. Here is the complete code that does all this:

            //declare string for filename
            string captureFileName = string.Empty;
            //declare image format
            ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();

            //rotate and save the image
            using (var imageStream = new InMemoryRandomAccessStream())
            {
                //generate stream from MediaCapture
                await captureManager.CapturePhotoToStreamAsync(format, imageStream);

                //create decoder and encoder
                BitmapDecoder dec = await BitmapDecoder.CreateAsync(imageStream);
                BitmapEncoder enc = await BitmapEncoder.CreateForTranscodingAsync(imageStream, dec);

                //roate the image
                enc.BitmapTransform.Rotation = BitmapRotation.Clockwise90Degrees;

                //write changes to the image stream
                await enc.FlushAsync();

                //save the image
                StorageFolder folder = KnownFolders.SavedPictures;
                StorageFile capturefile = await folder.CreateFileAsync("photo_" + DateTime.Now.Ticks.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);
                captureFileName = capturefile.Name;

                //store stream in file
                using (var fileStream = await capturefile.OpenStreamForWriteAsync())
                {
                    try
                    {
                        //because of using statement stream will be closed automatically after copying finished
                        await RandomAccessStream.CopyAsync(imageStream, fileStream.AsOutputStream());
                    }
                    catch 
                    {

                    }
                }
            }

Of course, we need to stop the preview after we captured the photo. It also makes all sense to load the saved image and display it to the user. This is the code to stop the preview:

        private async void CleanCapture()
        {

            if (captureManager != null)
            {
                if (isPreviewing == true)
                {
                    await captureManager.StopPreviewAsync();
                    isPreviewing = false;
                }
                captureManager.Dispose();

                previewElement.Source = null;
                previewElement.Visibility = Visibility.Collapsed;
                takenImage.Source = null;
                takenImage.Visibility = Visibility.Collapsed;
                captureButton.Content = "capture";
            }

        }

The result of above mentioned code (screenshot of preview left, captured photo right):

16by9Photo

Cropping the captured photo

Not all Windows Phone devices have an aspect ratio of 16:9. In fact, most devices in the market have an aspect ratio of 15:9, due to the fact that they are WVGA or WXGA devices (I talked a bit about this already in my second post). If we are just capturing the photo with the method above, we will have the same black bands in our image as we have in our preview. To get around this and capture a photo that has a true 15:9 resolution (makes sense for photos that get reused in apps, but less for real life photos), additional code is needed.

As with getting the right camera solution, I generated an Enumeration that holds all possible values as well as a helper method to detect which aspect ratio the currently used device has:

        public enum DisplayAspectRatio
        {
            Unknown = -1,

            FifteenByNine = 0,

            SixteenByNine = 1
        }

        private DisplayAspectRatio GetDisplayAspectRatio()
        {
            DisplayAspectRatio result = DisplayAspectRatio.Unknown;

            //WP8.1 uses logical pixel dimensions, we need to convert this to raw pixel dimensions
            double logicalPixelWidth = Windows.UI.Xaml.Window.Current.Bounds.Width;
            double logicalPixelHeight = Windows.UI.Xaml.Window.Current.Bounds.Height;

            double rawPerViewPixels = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
            double rawPixelHeight = logicalPixelHeight * rawPerViewPixels;
            double rawPixelWidth = logicalPixelWidth * rawPerViewPixels;

            //calculate and return screen format
            double relation = Math.Max(rawPixelWidth, rawPixelHeight) / Math.Min(rawPixelWidth, rawPixelHeight);
            if (Math.Abs(relation - (15.0 / 9.0)) < 0.01)
            {
                result = DisplayAspectRatio.FifteenByNine;
            }
            else if (Math.Abs(relation - (16.0 / 9.0)) < 0.01)
            {
                result = DisplayAspectRatio.SixteenByNine;
            }

            return result;
        }

In Windows Phone 8.1, all Elements use logical pixel size. To get the values that most of us are used to, we need to calculate the raw pixels from the logical pixels. After that, we use the same math operations I used already for detecting the ratio of the camera resolution (see post 2). I tried to calculate the values with the logical pixels as well, but this ended up in some strange rounding behavior and not the results I wanted. That’s why I use the raw pixel sizes.

Before we continue with capturing the photo, we are going to add a border that is displayed and shows the area which is captured to the user in XAML:

            

When we are cropping our photo, we need to treaten the BitmapEncoder and the BitmapDecoder separately. To crop an image, we  need to set the Bounds and the new Width and Height of the photo via the BitmapTransform.Bounds property. We also need to read the PixelData via the GetPixelDataAsync() method, apply the changed Bounds to it and pass them to BitmapEncoder via the SetPixelData() method.

At the end, we are flushing the changed stream data directly into the file stream of our StorageFile. Here is how:

            //declare string for filename
            string captureFileName = string.Empty;
            //declare image format
            ImageEncodingProperties format = ImageEncodingProperties.CreateJpeg();

            using (var imageStream = new InMemoryRandomAccessStream())
            {
                //generate stream from MediaCapture
                await captureManager.CapturePhotoToStreamAsync(format, imageStream);

                //create decoder and transform
                BitmapDecoder dec = await BitmapDecoder.CreateAsync(imageStream);
                BitmapTransform transform = new BitmapTransform();

                //roate the image
                transform.Rotation = BitmapRotation.Clockwise90Degrees;
                transform.Bounds = GetFifteenByNineBounds();

                //get the conversion data that we need to save the cropped and rotated image
                BitmapPixelFormat pixelFormat = dec.BitmapPixelFormat;
                BitmapAlphaMode alpha = dec.BitmapAlphaMode;

                //read the PixelData
                PixelDataProvider pixelProvider = await dec.GetPixelDataAsync(
                    pixelFormat,
                    alpha,
                    transform,
                    ExifOrientationMode.RespectExifOrientation,
                    ColorManagementMode.ColorManageToSRgb
                    );
                byte[] pixels = pixelProvider.DetachPixelData();

                //generate the file
                StorageFolder folder = KnownFolders.SavedPictures;
                StorageFile capturefile = await folder.CreateFileAsync("photo_" + DateTime.Now.Ticks.ToString() + ".jpg", CreationCollisionOption.ReplaceExisting);
                captureFileName = capturefile.Name;

                //writing directly into the file stream
                using (IRandomAccessStream convertedImageStream = await capturefile.OpenAsync(FileAccessMode.ReadWrite))
                {
                    //write changes to the BitmapEncoder
                    BitmapEncoder enc = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, convertedImageStream);
                    enc.SetPixelData(
                        pixelFormat,
                        alpha,
                        transform.Bounds.Width,
                        transform.Bounds.Height,
                        dec.DpiX,
                        dec.DpiY,
                        pixels
                        );

                    await enc.FlushAsync();
                }
            }

You may have notice the GetFifteenByNineBounds() method in the above code. As we need to calculate some values for cropping the image, I decided to separate them. They are not only providing values for the image to be cropped, but also size values for our earlier added Border that is used in my sample (download link at the end of the project) to show the size that the photo will have after our cropping (which is an automatic process in our case,). Here is the code:

        private BitmapBounds GetFifteenByNineBounds()
        {
            BitmapBounds bounds = new BitmapBounds();

            //image size is raw pixels, so we need also here raw pixels
            double logicalPixelWidth = Windows.UI.Xaml.Window.Current.Bounds.Width;
            double logicalPixelHeight = Windows.UI.Xaml.Window.Current.Bounds.Height;

            double rawPerViewPixels = DisplayInformation.GetForCurrentView().RawPixelsPerViewPixel;
            double rawPixelHeight = logicalPixelHeight * rawPerViewPixels;
            double rawPixelWidth = logicalPixelWidth * rawPerViewPixels;

            //calculate scale factor of UniformToFill Height (remember, we rotated the preview)
            double scaleFactorVisualHeight = maxResolution().Width / rawPixelHeight;

            //calculate the visual Width
            //(because UniFormToFill scaled the previewElement Width down to match the previewElement Height)
            double visualWidth = maxResolution().Height / scaleFactorVisualHeight;
            
            //calculate cropping area for 15:9
            uint scaledBoundsWidth = maxResolution().Height;
            uint scaledBoundsHeight = (scaledBoundsWidth / 9) * 15;

            //we are starting at the top of the image
            bounds.Y = 0;
            //cropping the image width
            bounds.X = 0;
            bounds.Height = scaledBoundsHeight;
            bounds.Width = scaledBoundsWidth;

            //set finalPhotoAreaBorder values that shows the user the area that is captured
            finalPhotoAreaBorder.Width = (scaledBoundsWidth / scaleFactorVisualHeight) / rawPerViewPixels;
            finalPhotoAreaBorder.Height = (scaledBoundsHeight / scaleFactorVisualHeight) / rawPerViewPixels;
            finalPhotoAreaBorder.Margin = new Thickness(
                                            Math.Floor(((rawPixelWidth - visualWidth) / 2) / rawPerViewPixels), 
                                            0,
                                            Math.Floor(((rawPixelWidth - visualWidth) / 2) / rawPerViewPixels), 
                                            0);
            finalPhotoAreaBorder.Visibility = Visibility.Visible;

            return bounds;
        }

Again, we need to apply raw pixels to achieve the best results here (I just pasted those lines in for this sample). To calculate the correct values for our Border, we need the scale factor between the screen and the preview resolution we used (which is the scaleFactorVisualHeight double).  Before we’re calculating the border values, we are setting the Width to resolution’s Height (we rotated, remember?) and calculate the matching 15:9 Height.

The Border values are based on the Width and Height of the cropped image, but scaled down by scaleFactorVisualHeight’s value and converted in raw pixel. The Margin positions the border accordingly on top of the preview element.

This is the result of above mentioned code (screenshot of preview left, captured photo right):

15by9Photo

That’s all you need to know to get started with basic photo capturing from within your Windows Phone 8.1 Runtime app. Of course, there are also other modifications that you can apply, and I mentioned already most of the classes that lead you to the matching methods and properties (click on the links to get to the documentation)

By the way, most of the code can be adapted in a Windows 8.1 app as well (with some differences, of course).

Sample project

As promised, you can download the sample here. It contains all code snippets I showed you and is able to run as you build and deploy it.

As always, feedback is welcome and I hope this post is helpful for some of  you.

Until the next time, happy coding!

Posted by msicc in Archive, 21 comments

How to capture a photo in your Windows Phone 8.1 Runtime app-Part II: some common modifications

Like promised in my first post about photo capturing, I will provide some common modification scenarios when using the MediaCapture API. This is what this post is about.

Choosing a camera

If you read my first post, you probably remember that the MediaCapture API automatically selected the front camera of my Lumia 1020. Like often, we have to write some additional code to switch between the cameras.

The cameras are listed in the Panels in the Windows.Devices.Enumeration Namespace. This namespace contains all “devices” that are connected to the phone and has different properties to detect the correct panel. We are going to use the DeviceClass to detect all video capture devices (which are normally also the photo capture devices on Windows Phone, but can be different on a PC/Tablet). As we want to switch between Front and Back, we are also detecting the EnclosureLocation. Here is how I implemented it:

        private static async Task<DeviceInformation> GetCameraID(Windows.Devices.Enumeration.Panel camera)
        {
            DeviceInformation deviceID = (await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture))
                .FirstOrDefault(x => x.EnclosureLocation != null && x.EnclosureLocation.Panel == camera);

            return deviceID;
        }

To make this Task actually useful, we are also updating the InitializePreview() method from the first part:

        private async void InitializePreview()
        {
            captureManager = new MediaCapture();

            var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);

            await captureManager.InitializeAsync(new MediaCaptureInitializationSettings
            {
                StreamingCaptureMode = StreamingCaptureMode.Video,
                PhotoCaptureSource = PhotoCaptureSource.Photo,
                AudioDeviceId = string.Empty,
                VideoDeviceId = cameraID.Id,
            });

            StartPreview();
        }

In this case, we  selected the back camera. To make the MediaCapture API actually use this device, we need to generate a new instance of MediaCaptureInitializationSettings, where we select the cameras Id as VideDeviceId. If you now start capturing, this is an exemplary result:

wp_ss_20141115_0001

Rotating the preview

However, this not quite satisfying, because the preview automatically uses the landscape orientation. Luckily, this can be changed with just one single line of code (that needs to be added before actually starting the preview):

captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);

Now the result looks like this:

wp_ss_20141115_0002

Note: the black bands on both sides may happen due to the fact that most devices have a 15:9 ratio (WXGA, WVGA). On Devices like the Lumia 830 or 930, which have a 16:9 ratio, the preview will use the full screen in portrait mode. I tried a lot of things to get rid of those bands already, sadly without success. Once I found a proper solution, I will write another blog post and link it here on how to do it (any tips are welcome).

Limiting resolution

Sometimes, we need to limit resolutions (for example resolution limits on other parts in our app). This is possible by detecting the supported solutions and matching them to the screen ratio. As we are using the whole screen for previewing, of course we want to get our captured photo to use the same space, too.

My way to do this is to calculate the screen ratio, and return an enumeration value. This is the easiest way, and can be easily used in the further code to limit the resolution. The enumeration looks like this:

public enum CameraResolutionFormat
{
    Unknown = -1,

    FourByThree = 0,

    SixteenByNine = 1
}

And this is my helper to match the screen format (which is always wide screen on Windows Phone):

        private CameraResolutionFormat MatchScreenFormat(Size resolution)
        {
            CameraResolutionFormat result = CameraResolutionFormat.Unknown;

            double relation = Math.Max(resolution.Width, resolution.Height) / Math.Min(resolution.Width, resolution.Height);
            if (Math.Abs(relation - (4.0 / 3.0)) < 0.01)
            {
                result = CameraResolutionFormat.FourByThree;
            }
            else if (Math.Abs(relation - (16.0 / 9.0)) < 0.01)
            {
                result = CameraResolutionFormat.SixteenByNine;
            }

            return result;
        }

We could easily extend the calculation to 15:9, too. However, as the most camera resolutions are 4:3 or 16:9, this makes no sense in our use case (as 15:9 is still a widescreen format). The next thing we need to add is another helper to get the highest possible resolution for our photo and the preview. We are achieving this by generating a new object of type VideoEncodingProperties:

        private VideoEncodingProperties maxResolution()
        {
            VideoEncodingProperties resolutionMax = null;

            //get all photo properties
            var resolutions = captureManager.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.Photo);

            //generate new list to work with
            List<VideoEncodingProperties> vidProps = new List<VideoEncodingProperties>();

            //add only those properties that are 16:9 to our own list
            for (var i = 0; i < resolutions.Count; i++)
            {
                VideoEncodingProperties res = (VideoEncodingProperties)resolutions[i];

                if (MatchScreenFormat(new Size(res.Width, res.Height)) != CameraResolutionFormat.FourByThree)
                {
                    vidProps.Add(res);
                }
            }

            //order the list, and select the highest resolution that fits our limit
            if (vidProps.Count != 0)
            {
                vidProps = vidProps.OrderByDescending(r => r.Width).ToList();

                resolutionMax = vidProps.Where(r => r.Width < 2600).First();                
            }

            return resolutionMax;
        }

What I am doing here: I read all available VideoEncodingProperties for the MediaStreamType Photo. As I mentioned before, we need only wide screen resolution for Windows Phone, that’s why I add only those that have not a 4:3 ratio to my list. Then I am using LINQ to order the list and select the highest resolution from that list.

Using this helper is also very easy, done with one line of code before starting the preview and best also before rotating the preview:

await captureManager.VideoDeviceController.SetMediaStreamPropertiesAsync(MediaStreamType.Photo, maxResolution());

This way, we are able to respect any resolution limits that we might face while developing our app, while keeping the photo quality as high as possible.

        private CameraResolutionFormat MatchScreenFormat(Size resolution)
        {
            CameraResolutionFormat result = CameraResolutionFormat.Unknown;

            double relation = Math.Max(resolution.Width, resolution.Height) / Math.Min(resolution.Width, resolution.Height);
            if (Math.Abs(relation - (4.0 / 3.0)) < 0.01)
            {
                result = CameraResolutionFormat.FourByThree;
            }
            else if (Math.Abs(relation - (16.0 / 9.0)) < 0.01)
            {
                result = CameraResolutionFormat.SixteenByNine;
            }

            return result;
        }

Focus

Focusing on objects in your photo is quite important. Sadly, it seems that currently we are not able to have a one solution fits all devices solution for using AutoFocus. I experimented a lot with it, and finally I got aware of known issues with Nokia drivers and the new MediaCapture API’s, as described here. Microsoft is working with Nokia (or their devices department) to fix this problem.

The only solution I got working for an Runtime app is to use manual focus. All other attempts gave me one Exception after the other, be it on cancelling the preview or be it on while previewing itself.  I’ll write another post on how to use the AutoFocus as soon as it is working like it should. In the meantime, here is my solution for manual focusing.

First, add a Slider control in your XAML page:

<Slider x:Name="FocusValueSlider" Maximum="1000" Minimum="0" Grid.Row="0" Margin="12,0,15,0" Header="adjust focus:" ValueChanged="FocusValueSlider_ValueChanged" Value="500" SmallChange="25" LargeChange="100" ></Slider>

Notice that as with any slider, you need to follow the order: Set Maximum first, then Minimum. If you do not, you will likely get an unusable Slider in return. If the VideoDeviceController.Focus property would work (seems like it is also affected by the above mentioned driver problems), we could read and set the Slider values from its MediaDeviceControl.Capabilities property. I tried to read them at any stage of previewing, but their values are always 0.0, null and false. The range up to 1000 fits in very well on all devices I tested (Lumia 920, 930 and 1020).

Ok, enough of whining. Let’s have a look at my solution. First, we need to generate a small helper that allows us to adjust the focus based on the slider values:

        private async void SetFocus(uint? focusValue = null)
        {
            //try catch used to avoid app crash at startup when no CaptureElement is active
            try
            {
                //setting default value
                if (!focusValue.HasValue)
                {
                    focusValue = 500;
                }

                //check if the devices camera supports focus control
                if (captureManager.VideoDeviceController.FocusControl.Supported)
                {
                    //disable flash assist for focus control
                    captureManager.VideoDeviceController.FlashControl.AssistantLightEnabled = false;

                    //configure the FocusControl to manual mode
                    captureManager.VideoDeviceController.FocusControl.Configure(new FocusSettings() { Mode = FocusMode.Manual, Value = focusValue, DisableDriverFallback = true });
                    //update the focus on our MediaCapture
                    await captureManager.VideoDeviceController.FocusControl.FocusAsync();
                }
            }
            catch { }
        }

This methods checks if the current camera supports Focus, and sets its value according to the slider. The AssistantLight is disabled in this case. Its default is enabled (true).

To add the possibility to adjust the focus, we need to configure our own FocusSettings that tell the camera that we are focusing manually based on the slider’s value. Finally, we need to perform the focusing action by calling the FocusControl’s FocusAsync method.

The next step is to hook up to changes in the slider values within the FocusValueSlider_ValueChanged event:

        private void FocusValueSlider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            try
            {
                //convert double e.NewValue to uint and call SetFocus()
                uint focus = Convert.ToUInt32(e.NewValue);
                SetFocus(focus);
            }
            catch 
            {
                
            }
        }

Now every move of the slider will change the focus of the preview and of course also of the captured photo (which we will learn more about in the third post of this series).  To initialize our Focus correctly with the value of 500 we set in XAML, just call SetFocus(); before you start the preview. Here is the result:

focus screenshot

 

Disclaimer: I do not know if this follows best practices, but it works. If you have feedback for the above mentioned code snippets, feel free to leave a comment below.

In the third and last post I’ll show you how to save the images (also in different folders or only within the app).

Until then, happy coding!

Posted by msicc in Archive, 9 comments

How to capture a photo in your Windows Phone 8.1 Runtime app–Part I: the preview of the photo to capture

With the recent release of the public beta of RandR, I also learned a lot about taking photos from within an Windows Phone 8.1 app. There are several differences to Windows Phone 8, so I decided to start this three part series on how to capture a photo in your app (it would be too much for one single post).

The series will contain following topics:

The series concentrates on basic features to enable you to get started. I am adding relevant links to those posts, and at the end of the series, I will also attach a sample project.

Let’s start

Before we can use MediaCapture, please make sure that you enable Webcam and Microphone in your app’s Package.appxmanifest file. Then, we need is an Element that shows us the preview of the content we want to capture. In a Runtime app, we are using a CaptureElement for this. We also need to buttons, one to start/cancel the preview operation, and one to save the photo. Of course we want to show the photo we have taken, so we need also an image element.

Add this code to your XAML page:

<Grid>
    <CaptureElement x:Name="previewElement" Stretch="UniformToFill" />
    <Image x:Name="takenImage" Stretch="UniformToFill" Visibility="Collapsed"></Image>
</Grid>
<Grid VerticalAlignment="Bottom">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="Auto"></RowDefinition>
        <RowDefinition Height="*"></RowDefinition>
    </Grid.RowDefinitions>
<Button Grid.Row="0" x:Name="captureButton" Content="capture" Click="captureButton_Click" HorizontalAlignment="Stretch" Margin="12,0"/>
<Button Grid.Row="1" x:Name="saveButton" Content="save" Click="saveButton_Click" HorizontalAlignment="Stretch" Margin="12,0"/>
</Grid>

Asign the click handlers to the code behind file, where we will also continue to work now.

Before we’ll have a look at the preview code, we need to enable our app to obtain the whole screen. This makes all sense, as we want to capture a photo, and of course we want to see as much as possible in the preview. Add these two lines to the constructor of the page:

var appView = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView();
appView.SetDesiredBoundsMode(ApplicationViewBoundsMode.UseCoreWindow);

The ApplicationViewBoundsMode enumeration has two values (UseVisible and UseCoreWindow). The later one uses the whole screen (even behind the SystemTray and also behind the BottomAppBar) and suits our needs. Only one thing to remember for your app: You need to set the Margins in this case to get your UI  right.

The preview code

Windows Runtime apps use the MediaCapture class for all photo and video capturing.

To enable your app to preview the things you want to capture, we first need to initialize the MediaCapture. We are doing this by a helper method, as we will need it in the next post to create some options for our MediaCapture. After declaring a page wide variable for the MediaCapture, add the following code to your code behind file:

       private async void InitializePreview()
       {
           captureManager = new MediaCapture();

           await captureManager.InitializeAsync();
           StartPreview();
       }

To make the initialized MediaCapture actually doing something, we also need to start the preview:

private async void StartPreview()
{

    previewElement.Source = captureManager;
    await captureManager.StartPreviewAsync();
              
    isPreviewing = true;
}

What we are doing is to set the Source of our previewElement that we declared in XAML to our captureManager and asynchronously start the preview. The isPreviewing Boolean is used to detect if we are actually previewing. We’ll need it in our method to stop the preview. This is very important. If you do not stop the preview, chances are high that you will freeze your phone or make the camera unusable for other apps, too!

To stop the preview, add this code:

private async void CleanCapture()
{
    if (captureManager != null)
    {
        if (isPreviewing == true)
        {
            await captureManager.StopPreviewAsync();
            isPreviewing = false;
        }
        previewElement.Source = null;
        captureButton.Content = "capture";
        captureManager.Dispose();
    }
}

 

We need to do a double check here: First, we need to see if we have a captureManager instance. Then, if we are previewing, we are going to stop it. If we are no longer previewing, we are setting the CaptureElement Source to null, rename our button and free all resources our captureManager used with the Dispose() method.

Now that we have everything for the preview in place, we are able to connect it to our captureButton:

private void captureButton_Click(object sender, RoutedEventArgs e)
{
    if (isPreviewing == false)
    {
        InitializePreview();
        captureButton.Content = "cancel";
    }
    else if (isPreviewing == true)
    {
        CleanCapture();
    }
}

Now we are already able to start previewing (without any options) on our phone:

wp_ss_20141114_0002

You might get similar  strange results if you start capturing. For example, the preview on my Lumia 1020 is flipped upside down and the front camera is used.

How we are going to change this, is topic of the second part.

Until then, happy coding!

Posted by msicc in Archive, 1 comment