Home > C#, Universal Windows Platform > A Behavior for CameraPressed event in Universal Windows apps

A Behavior for CameraPressed event in Universal Windows apps

30/05/2016

If we’re developing a Universal app that uses the camera, on Windows Mobile we may want to use the hardware camera button for example to take a photo. Of course, we need to take into account that on desktops and tablets we don’t have this feature. To add a bit more complexity, suppose we’re following the MVVM pattern. So, how can we manage this scenario?

In order to handle the hardware camera button, we just need a reference to the Windows Mobile Extensions for the UWP. In this way, we obtain access to Mobile specific features:

Windows Mobile Extensions for the UWP

Windows Mobile Extensions for the UWP

As we’re working with MVVM, the best solution is to create a custom Behavior. First of all, let’s add its reference through NuGet, searching for the package Microsoft.Xaml.Behaviors.Uwp.Managed:

UWP Behavoirs package on NuGet

UWP Behavoirs package on NuGet

Now we have all the prerequisites to create the CameraPressedBehavior:

[ContentProperty(Name = "Actions")]
public sealed class CameraPressedBehavior : Behavior
{
    public static readonly DependencyProperty ActionsProperty = 
        DependencyProperty.Register(
        "Actions",
        typeof(ActionCollection),
        typeof(CameraPressedBehavior),
        new PropertyMetadata(null));

    public ActionCollection Actions
    {
        get
        {
            var actionCollection = (ActionCollection)
                this.GetValue(ActionsProperty);

            if (actionCollection == null)
            {
                actionCollection = new ActionCollection();
                this.SetValue(ActionsProperty, actionCollection);
            }

            return actionCollection;
        }
    }

    [System.Runtime.CompilerServices.PlatformSpecific]
    private readonly bool isTypePresent;

    public CameraPressedBehavior()
    {
        isTypePresent = 
            Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
                "Windows.Phone.UI.Input.HardwareButtons");
    }

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

        if (isTypePresent)
            HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
    }

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

        if (isTypePresent)
            HardwareButtons.CameraPressed -= HardwareButtons_CameraPressed;
    }

    private void HardwareButtons_CameraPressed(object sender, CameraEventArgs e)
    {
        Interaction.ExecuteActions(AssociatedObject, Actions, EventArgs.Empty);
    }       
}

At lines 4-26 we define the Actions dependency property that stores the action to be executed when then button is pressed. This part of code is usually present in every behavior.

Then, in the Behavior costructor (lines 31-36), we use the ApiInformation.IsTypePresent method to check whether the Windows.Phone.UI.Input.HardwareButtons type is actually present, i.e. if the platform provides access to hardware buttons. If this is the case, in the OnAttached method (lines 38-44) we register for the CameraPressed event, otherwise we do nothing. In the same way, in the OnDetaching method we remove the event registration, if necessary. Thanks to these checks, the code can safely be executed also on platforms that don’t have hardware buttons.

Finally, in the CameraPressed event handler (lines 54-57), we call the Interaction.ExecuteActions static method, that in turn executes all the registered actions.

Now we can use the Behavior in our XAML page. For example:

<Page
    ...
    xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" 
    xmlns:Interactions="using:Microsoft.Xaml.Interactions.Core"
    xmlns:behaviors="using:See4Me.Behaviors"
    ...>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        ...
        <Interactivity:Interaction.Behaviors>
            <behaviors:CameraPressedBehavior>
                <Interactions:InvokeCommandAction 
                              Command="{Binding TakePhotoCommand}"  />
            </behaviors:CameraPressedBehavior>            
        </Interactivity:Interaction.Behaviors>
    </Grid>
</Page>

We add the CameraPressedBehavoir to the page (lines 10-15) so that, when the button is pressed, the InvokeCommandAction is executed, causing the TakePhotoCommand to be run. As said before, this behavior on desktops and tables has no effects, so it actually works only on phones.

  1. No comments yet.
  1. 31/05/2016 at 13:24
Comments are closed.
%d bloggers like this: