Developing Tizen Samsung Galaxy Watch Apps with .NET and C# - Getting Started

This article assumes you have set up the Tizen/Visual Studio development environment as outlined in this previous article.

Installing the Watch Emulator

The first step is to install the relevant emulator so you don’t need a physical Samsung Galaxy Watch. To do this open Visual Studio and click  Tools –> Tizen –> Tizen Emulator Manager

This will bring up the Emulator Manager, click the Create button, then Download new image, check the WEARABLE profile, and click OK. This will open the Package Manager and download the emulator.

Installing the Tizen Wearable emulator in Visual Studio

Once the installation is complete, if you open the Emulator Manager, select Wearable-circle and click Launch you should see the watch emulator load as shown in the following screenshot:

watchemulator

Creating a Watch Project

In Visual Studio, create a new Tizen Wearable Xaml App project  which comes under the Tizen 5.0 section.

Once the project is created and the with the emulator running, click the play button in Visual Studio (this will be something like “W-5.0-circle-x86…” ).

The app will build and be deployed to the emulator – you may have to manually switch back to the emulator if it isn’t brought to the foreground automatically. You should now see the emulator with the text “Welcome to Xamarin.Forms!”.

This text comes from the MainPage.xaml:

<?xml version="1.0" encoding="utf-8" ?>
<c:CirclePage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:c="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms"
             x:Class="TizenWearableXamlApp1.MainPage">
  <c:CirclePage.Content>
    <StackLayout>
      <Label Text="Welcome to Xamarin.Forms!"
          VerticalOptions="CenterAndExpand"
          HorizontalOptions="CenterAndExpand" />
    </StackLayout>
  </c:CirclePage.Content>
</c:CirclePage>

Modifying the Basic Template

As a very simple (and quick and dirty, no databinding, MVVM, etc.) example, the MainPage.xaml can be changed to:

<?xml version="1.0" encoding="utf-8" ?>
<c:CirclePage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:c="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms"
             x:Class="TizenWearableXamlApp1.MainPage">
    <c:CirclePage.Content>
        <StackLayout HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand">
            <Label x:Name="HappyValue" Text="5" HorizontalTextAlignment="Center"></Label>
            <Slider x:Name="HappySlider" Maximum="10" Minimum="1" Value="5" ValueChanged="HappySlider_ValueChanged" ></Slider>
            <Button Text="Go" Clicked="Button_Clicked"></Button>
    </StackLayout>
  </c:CirclePage.Content>
</c:CirclePage>

And the code behind MainPage.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Tizen.Wearable.CircularUI.Forms;
using System.Net.Http;

namespace TizenWearableXamlApp1
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MainPage : CirclePage
    {
        private int _happyValue = 5;

        public MainPage()
        {
            InitializeComponent();
        }

        private async void Button_Clicked(object sender, EventArgs e)
        {
            HttpClient client = new HttpClient();

            var content = new StringContent($"{{ \"HappyLevel\" : {_happyValue} }}", Encoding.UTF8, "application/json");

            var url = "https://prod-29.australiasoutheast.logic.azure.com:443/workflows/[REST OF URL REDACTED FOR PRIVACY/SECURITY]";

            var result = await client.PostAsync(url, content);
            
        }

        private void HappySlider_ValueChanged(object sender, ValueChangedEventArgs e)
        {
            _happyValue = (int)Math.Round(HappySlider.Value);

            HappyValue.Text = _happyValue.ToString();
        }
    }
}

The preceding code essentially allows the user to specify how happy they are using a slider, and then hit the Go button. This button makes an HTTP POST to a URL, in this example the URL is a Microsoft Flow HTTP request trigger.

The flow is shown in the following screenshot, it essentially takes the JSON data in the HTTP POST, uses the HappyLevel JSON value and sends a mobile notification to the Flow app on my iPhone.

Microsoft Flow triggered from HTTP request

Testing the App

To test the app, run it in Visual Studio:

Xamarin Forms app running in Samsung Galaxy Watch emulator

Tapping the Go button will make the HTTP request and initiate the Microsoft Flow, and after a few moments, the notification being sent to the phone:

Microsoft Flow notification on iPhone

If you want to fill in the gaps in your C# knowledge be sure to check out my C# Tips and Traps training course from Pluralsight – get started with a free trial.

SHARE:

Databinding Conversions Using Functions in UWP XAML Apps

When using compiled data bindings using the x:Bind syntax in UWP apps, as an alternative to using an IValueConverter, a function can instead be defined. This means that whenever a value needs converting from the source object to the XAML property, the function will be called rather than an IValueConverter. This functionality is available from the Windows 10 Anniversary update so your UWP app in Visual Studio will need to be targeting version 14393 or later.

As an example, suppose there was already some existing code that maps whether a customer is considered high risk to a color, e.g. high risk customers should be shown in red. One way to accomplish this when databinding in the UI is to create an IValueConverter and then call into the existing code to do the conversion. Another option is to simply call the function from the XAML databinding – this reduces the need to write the additional IValueConverter implementation.

Take the following XAML:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="{x:Bind CustomerName}" FontSize="36"></TextBlock>
            <TextBlock Text="{x:Bind IsHighRisk}" FontSize="36"></TextBlock>
        </StackPanel>
    </Grid>
</Page>

In the preceding XAML, we want the IsHighRisk  TextBlock to appear in red if the customer is a high risk customer.

Imagine we already had some code to do this as follows:

using Windows.UI;
using Windows.UI.Xaml.Media;

namespace App1
{
    static class RiskColorMapper
    {
        public static Brush ToColor(bool isHighRisk)
            => isHighRisk ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Olive);
    }
}

We can now use the x:Bind syntax to call into this function and bind the foreground color to the boolean value of the IsHighRisk property as the following modified XAML demonstrates:

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel>
            <TextBlock Text="{x:Bind CustomerName}" FontSize="36"></TextBlock>
            <TextBlock Text="{x:Bind IsHighRisk}" FontSize="36" Foreground="{x:Bind local:RiskColorMapper.ToColor(IsHighRisk)}"></TextBlock>
        </StackPanel>
    </Grid>
</Page>

Now if we run the app with IsHighRisk set to false the text foreground is olive, if IsHighRisk is true the text will be red as the following screenshots show:

UWP data binding to function screenshot

UWP data binding to function screenshot

If the binding is TwoWay, the BindBack binding property can also be added that points to a function to do the reverse conversion.

For more info check out MSDN.

SHARE:

Centralising RaiseCanExecuteChanged Logic in an MVVM Light Portable View Model

When working with an MVVM Light sometime we need to “tell” the view that a command’s ability to be executed has changed.

For example, when a user clicks a Start button to start a countdown, the Start button should be disabled and the pause button should then be enabled.

If we’re binding a button to an MVVM Light RelayCommand, the button will automatically disable when then RelayCommand’s CanExecute function returns false.

For this to work, when the user clicks Start, the command will execute, but then we need to tell the Start and Pause commands to raise their CanExecuteChanged events. To do this we can call the RaiseCanExecuteChanged method on each RelayCommand that logically makes sense for our application.

One approach is to put this in each property setter, for example:

public const string IsPlayingPropertyName = "IsPlaying";
protected  bool _isplaying;

public  bool IsPlaying
{
    get
    {
        return _isplaying;
    }

    set
    {
        if (_isplaying == value)
        {
            return;
        }

        RaisePropertyChanging(IsPlayingPropertyName);
        _isplaying = value;
        RaisePropertyChanged(IsPlayingPropertyName);
              
        // RAISE CANEXECUTECHANGED HERE IN PROP SETTER
        PauseCommand.RaiseCanExecuteChanged();
        StartCommand.RaiseCanExecuteChanged();
    }
}

Now when this IsPlaying property changes, the Pause and Start buttons commands can execute will be updated.

A problem with this approach is that the logic to decide which RelayCommands CanExecuteChanged event gets raised in response to which properties are changing is distributed through all the property setters in the ViewModel. This can make it hard to reason about the changes in state of the ViewModel.

One alternative approach is to centralise this logic in a single method.

More...

SHARE:

Using XAML Behaviours to stop MVVM Light Messenger Action Executing Multiple Times

In MVVM Light, when we derive our ViewModel from ViewModelBase, we inherit a Cleanup() method.

This method can be overridden, by default it will unregister all messages for the ViewModel, so calling Cleanup() on our view model will prevent multiple subscriptions occurring if we navigate back to the ViewModel and register it again.

But where do we call Cleanup() ?

One method is to get the View to call the ViewModel’s Cleanup() method when it is unloaded.

We could write a codebehind “shim” to cast the View’s DataContext to our ViewModel type then call its Cleanup() method.

Another method is to use the Behaviours SDK (XAML).

image

Once we add this reference we can add some namespaces in our View XAML:

xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
xmlns:core="using:Microsoft.Xaml.Interactions.Core"

Now in our page, we can add the following XAML:

<interactivity:Interaction.Behaviors>
    <core:EventTriggerBehavior EventName="Unloaded">
        <core:CallMethodAction TargetObject="{Binding}" MethodName="Cleanup" />
    </core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>

Now every time the Page’s Unloaded event is raised, the Cleanup() method will be called on our ViewModel, which will unregister all messages for the bound ViewModel.

SHARE:

Telling a View to display a Message Dialog from the ViewModel With MVVMLight in Windows 8.1 Store Apps

The technique below is one technique, others exist, but the design goals of this approach are:

  1. The ViewModel cannot know or reference the View
  2. The ViewModel should should not care how the View displays or interacts with the user (it could be a dialog box, a flyout, etc.)
  3. The ViewModel must be Portable Class Library compatible and View agnostic, e.g. not need to know about dialog buttons, etc.
  4. Choices the user makes in the View dialog should result in Commands being executed on the ViewModel
  5. The ViewModel must not specify the content of the message text, button labels, etc. – the View should be responsible for the text/content of the message

One way to think about these design goals is that the ViewModel is asking for some semantic message/dialog to be displayed in the View.

Defining a Message to be used with the MVVM Light Messenger

The way the ViewModel “tells” the View to create a dialog is by sending a message using the MVVM Light Messenger.

First we define a custom message:

using System.Windows.Input;
using GalaSoft.MvvmLight.Messaging;

namespace Project.Portable.ViewModel.Messages
{
    public class ShowDialogMessage : MessageBase
    {
        public ICommand Yes { get; set; }
        public ICommand No { get; set; }
        public ICommand Cancel { get; set; }
    }
}

This message allows us to define the commands that the view will call, based on the choice that the user makes in the dialog.

More...

SHARE:

Updating Your Windows 8 App to Windows 8.1: Dealing With Coloured Fonts

With Windows 8.1, font characters (glyphs) can now contain coloured layers.

In a Windows 8.0 app, this XAML:

<TextBlock>$★☺☹❤✈⛱⛺⛵⚽✘✔☀⛅☕⛄❓♀♂❋❄✹</TextBlock>

Will produce the following (black and white) characters:

image

In Windows 8.1 this behaviour is different by default.

More...

SHARE:

Theming and Styling Your Windows Store App the Easy Way

This article shows one way of choosing and using a colour scheme in your Windows Store app.

The default style looks like this:

image

Step 1 – Choose a Colour Palette

We can use our fave colours or use a tool such as Adobe Kuler to help us come up with a scheme.

The screen shot below shows a Kuler theme “kathy 1” and it’s RGB values.

image

Our styled app will contain these colours.

More...

SHARE:

Creating an “Add New” Item Template in a Windows 8 App ListView

A common UI pattern is to have a list of things on screen and at the end of the list have a plus icon (or something) that triggers your “add new item” code.

For example, in the Weather app:

cdt_weatherapp

For example, say we want to display a list of friends in a XAML ListView and at the bottom of the list have a “+” that adds a new friend.

public class Friend
{
    public string Name { get; set; }
}

The first step is to enable us to differentiate between what is an actual friend in the list and what is the “add new placeholder” item.

More...

SHARE:

Binding a Dynamically Created WPF Control’s ItemTemplate to a DataTamplate Defined in XAML

I was asked a question about this on Twitter, so thought I’d create a quick post about it.

The example below shows how to use a DataTemplate that is defined in XAML with a ListView control that is dynamically created in the code behind.

1 Create a New WPF Application

Create  WPF application project in Visual Studio.

2 Create The basic XAML

Replace the contents of the MainWindow XAML to the following:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="DaysDataTemplate">
            <Grid Background="Cyan">
                <TextBlock Text="{Binding}"></TextBlock>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <Grid Name="RootContainer" />
</Window>

This defines a DataTemplate called DaysDataTemplate that simply binds the value and has a cyan background so we can see if it is being applied.

We also give the root container (Grid) a name RootContainer so we can reference it later in the code behind.

More...

SHARE:

MVVM Light Telling the View to play Storyboards

Sometimes you want to tell the view to play an animation (Storyboard). One simple way to do this is to define a StartStoryboardMessage class, populate this with the name of a Storyboard to play, then send it to the Messenger.

public class StartStoryboardMessage
{
    public string StoryboardName { getset; }
    public bool LoopForever { getset; }
}

In the viewmodel when you want to tell the view to play an animation:

Messenger.Default.Send(new StartStoryboardMessage { StoryboardName = "TimerFinAnimation",LoopForever=true });

The view (i.e. in the code-behind) registers for these messages:

Messenger.Default.Register<StartStoryboardMessage>(this, x => StartStoryboard(x.StoryboardName, x.LoopForever));

...

private void StartStoryboard(string storyboardName, bool loopForever)
{
    var storyboard = FindName(storyboardName) as Storyboard;
    if (storyboard != null)
    {
        if (loopForever) 
            storyboard.RepeatBehavior = RepeatBehavior.Forever;
        else
            storyboard.RepeatBehavior = new RepeatBehavior(1);
        storyboard.Begin();
    }
}

SHARE: