'ReactiveUI Bind an Enum Property to a Color Property in View Model

I am starting my first Reactive UI Project. I have an enum, and I want to map a specific color to a specific enum value. How could I accomplish this using Reactive UI? So when Status changes the TextColor changes.

Say I wanted to map

  • Running -> Green
  • Idle -> Orange
  • Faulted -> Red
  • Manual -> Blue

Here is my View Model

public enum Status { Running, Idle, Faulted, Manual}

public class MachineStatusViewModel : ReactiveObject
{
    public string Name;
    public Status Status;
    public System.Drawing.Color TextColor;

    public MachineStatusViewModel()
    {           

    }
}


Solution 1:[1]

The better approach is to use the OneWayBind operator over WhenAnyValue

this.OneWayBind(this.ViewModel, vm => vm.Status, view => view.TextColor, GetColor);

private Color GetColor(Status status)
{
    switch (status)
    {
        case Status.Running:
            return Color.Green;
        case Status.Idle:
            return Color.Orange;
        case Status.Faulted:
            return Color.Red;
        case Status.Manual:
            return Color.Blue;
    }
}

Solution 2:[2]

One more option is to go with resource dictionary. It can allow you to substitute one dictionary with another or define themed resources easily without hardcoding values to return. Simple example for your case:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Color x:Key="Running.Color" G="255"/>
    <Color x:Key="Idle.Color" R="255" G="165"/>
    <Color x:Key="Faulted.Color" R="255"/>
    <Color x:Key="Manual.Color" B="255"/>
</ResourceDictionary>

Then you use this dictionary in your view's xaml as a merged one (i.e. in Window)

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/<AssemblyName>;component/<Resource-Dictionary-File>.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

And the usage:

this.WhenAnyValue(x => x.ViewModel.Status)
    .Select(x => FindResource($"{x}.Color"))
    .BindTo(this, view => view.TextColor);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Glenn Watson
Solution 2 vkolesnik