C# WPF RGB Colour Viewer


Here is an example of a partially complete, small Windows project that incorporates some of the WPF concepts presented in previous posts. The user is presented with three sliders that they can use to set the RGB colour numbers and view a rectangle showing the colour represented by the RGB numbers they have chosen. Also, they can enter the three numbers directly into text boxes. However the text boxes do not update the slider until the text box loses its focus. The user can press the Tab key to change the focus. When the slider is adjusted by the user, the corresponding RGB number adjusts and the rectangle’s colour adjusts. The number range for each slider is zero to 255 and contains no fractions. You also want to prevent the user from entering invalid data such as alphabetical characters. If they do enter non-numeric characters and the text box loses its focus, the text box automatically adjusts to zero. If the user enters a number greater than 255, and the text box loses its focus, the text box automatically adjusts to 255.

ColourViewer

There are lots of colour viewers/pickers on the Internet that have many more features than this one. For example, go to the w3schools.com site for their color picker.

Building the Project

We need to design the interface first. We can use a previous post on Value Converters to help with setting binding the text boxes to their sliders and not allowing any decimal places. We also need to bind the text boxes to the rectangle to display the appropriate colour. We also use events. We use the ValueChanged event of the three sliders. When the value changes, we call a function that adjusts the colour in the rectangle by reading values in the three text boxes and assigning them to the Color struct of the SolidColorBrush object used to Fill the rectangle.

  • Text boxes can change the slider.
  • The sliders can change the text boxes and the rectangle’s colour.

Below is the markup: MainWindow.xaml

<Window x:Class="MikeColour2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TwoWayConverter"
        mc:Ignorable="d"
        Title="Colour Viewer" Height="304" Width="524">
    <Canvas>
        <Rectangle Name="Rect" HorizontalAlignment="Left" Height="229" Stroke="Black" VerticalAlignment="Top" Width="79" Canvas.Left="416" Canvas.Top="21" >
            <Rectangle.Fill>
                <SolidColorBrush>
                    <SolidColorBrush.Color>
                        <Color>
                            <Color.A>255</Color.A>
                            <Color.R>0</Color.R>
                            <Color.G>0</Color.G>
                            <Color.B>0</Color.B>
                        </Color>
                    </SolidColorBrush.Color>
                </SolidColorBrush>
            </Rectangle.Fill>
        </Rectangle>
        <Slider x:Name="sliderRed" Height="40" Canvas.Left="63" Canvas.Top="107" Width="247" Maximum="255" SmallChange="1" LargeChange="10" ValueChanged="sliderRed_ValueChanged"/>
        <Slider x:Name="sliderGreen" Height="39" Canvas.Left="63" Canvas.Top="167" Width="247"  Maximum="255" SmallChange="1" LargeChange="10" ValueChanged="sliderGreen_ValueChanged"/>
        <Slider x:Name="sliderBlue" Height="32" Canvas.Left="63" Canvas.Top="225" Width="247"  Maximum="255" SmallChange="1" LargeChange="10" ValueChanged="sliderBlue_ValueChanged"/>
        <TextBox x:Name="textBoxRed" Height="25" Canvas.Left="323" TextWrapping="Wrap" Canvas.Top="104" Width="59"  >
            <TextBox.Text>
                <Binding ElementName="sliderRed" Path="Value">
                    <Binding.Converter>
                        <local:DisplayTwoDecPlaces>
                        </local:DisplayTwoDecPlaces>
                    </Binding.Converter>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox x:Name="textBoxGreen" Height="25" Canvas.Left="323" TextWrapping="Wrap" Canvas.Top="167" Width="59" >
            <TextBox.Text>
                <Binding ElementName="sliderGreen" Path="Value">
                    <Binding.Converter>
                        <local:DisplayTwoDecPlaces>
                        </local:DisplayTwoDecPlaces>
                    </Binding.Converter>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBox x:Name="textBoxBlue" Height="25" Canvas.Left="323" TextWrapping="Wrap" Canvas.Top="225" Width="59" >
            <TextBox.Text>
                <Binding ElementName="sliderBlue" Path="Value">
                    <Binding.Converter>
                        <local:DisplayTwoDecPlaces>
                        </local:DisplayTwoDecPlaces>
                    </Binding.Converter>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <Label x:Name="label1" Content="Adjust the slider or numbers (0-255) to see the colour." Height="26" Canvas.Left="10" Canvas.Top="10" Width="393"/>
        <Label x:Name="label2" Content="After typing a number, press the tab key." Height="31" Canvas.Left="10" Canvas.Top="41" Width="317"/>
        <Label x:Name="label" Content="Red" Height="25" Canvas.Left="10" Canvas.Top="104" Width="48"/>
        <Label x:Name="label_Copy" Content="Green" Height="25" Canvas.Left="10" Canvas.Top="167" Width="48"/>
        <Label x:Name="label_Copy1" Content="Blue" Height="25" Canvas.Left="10" Canvas.Top="225" Width="48"/>
    </Canvas>
</Window>

Below is the code behind: MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MikeColour2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void UpdateRectangleColour()
        {
            string redStringValue, greenStringValue, blueStringValue;
            byte redByteValue, greenByteValue, blueByteValue;
            // get the values in the text boxes as strings and then convert
            // to bytes and store in variables of type byte.
            redStringValue = textBoxRed.Text;
            byte.TryParse((string)redStringValue, out redByteValue);
            greenStringValue = textBoxGreen.Text;
            byte.TryParse((string)greenStringValue, out greenByteValue);
            blueStringValue = textBoxBlue.Text;
            byte.TryParse((string)blueStringValue, out blueByteValue);
            // Update the colour of the rectangle
            Rect.Fill = new SolidColorBrush(Color.FromRgb(redByteValue, greenByteValue, blueByteValue));
        }
        private void sliderRed_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateRectangleColour();
        }
        private void sliderGreen_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateRectangleColour();
        }
        private void sliderBlue_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            UpdateRectangleColour();
        }
    }
}

Below is the Two Way Converter class: DisplayTwoDecPlaces.cs

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

namespace TwoWayConverter
{
    // You must specify the ValueConversion attribute in square brackets
    //           type of the source,type of the target
    [ValueConversion(typeof(double), typeof(string))]
    public class DisplayTwoDecPlaces : IValueConverter
    {
        public object Convert(object value, Type targetType,
                object parameter, System.Globalization.CultureInfo culture)
        {   // slider was moved
            // convert from double to a string with no decimal places
            double dValue = (double)value;
            return dValue.ToString("F0");  // F1 is one decimal place and so on.
        }
        public object ConvertBack(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
        {   // text box changed
            // convert from string to double
            double dValue;
            double.TryParse((string)value, out dValue);
            return dValue;
        }
    }
}

Leave a comment

Your email address will not be published. Required fields are marked *