Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
Does anyone here know of a good, free (preferably) toggle switch style control for winforms? (e.g. like the switch control in iOS).
Posted 22-Oct-12 15:39pm
Comments
Sergey Alexandrovich Kryukov at 22-Oct-12 20:57pm
   
Not clear. What exactly should it do? How about a check box all it does is toggle :-)
--SA
Zac Greve at 22-Oct-12 21:20pm
   
It should act like the switch control in iOS.
Zac Greve at 22-Oct-12 21:22pm
   
Like the on/off switches in the iOS options area. Just as TheCardinal suggested.
Sergey Alexandrovich Kryukov at 22-Oct-12 23:48pm
   
Sure, thank you for the confirmation. Please see my comment to TheCardinal solution.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

i have created a custom control for my metro ui look, the toggle control from the windows 8 pc settings
 
create a usercontrol and add 1 label
 
public partial class ToggleSwitch : UserControl
   {
       public Color ColorToggleOn { get; set; }
       public bool istoggleStatus { get; set; }
 
       public ToggleSwitch()
       {
           InitializeComponent();
       }
 
       private void ToggleSwitch_Load(object sender, EventArgs e)
       {
           if (istoggleStatus) {
               isON();
           }
           else {
               isOFF();
           }
       }
 
       protected override void OnMouseDown(MouseEventArgs e)
       {
           base.OnMouseDown(e);
           SetToggleControlStatus(istoggleStatus);
       }
 
       private void SetToggleControlStatus(bool isToggle)
       {
           if (isToggle) {
               isToggle = false;
               this.BackColor = Color.Silver;
               this.label1.Dock = DockStyle.Left;
           }
           else {
               isToggle = true;
               this.BackColor = this.ColorToggleOn;
               this.label1.Dock = DockStyle.Right;
           }
           istoggleStatus = isToggle;
       }
 
       private void isOFF()
       {
           this.BackColor = Color.Silver;
           this.label1.Dock = DockStyle.Left;
       }
 
       private void isON()
       {
           this.BackColor = ColorToggleOn;
           this.label1.Dock = DockStyle.Right;
       }
 
       protected override void OnPaint(PaintEventArgs e)
       {
            if (istoggleStatus) {
               isON();
           }
           else {
               isOFF();
           }
           base.OnPaint(e);
        }
 

   }
 

i know this need more cleaning up but it works Big Grin | :-D this is how it looks like
 
http://www.computerperformance.co.uk/images/win8/pc_settings_sync.jpg[^]
  Permalink  
Comments
Sergey Alexandrovich Kryukov at 22-Oct-12 23:47pm
   
Not perfect look and code, but I like the clever and labor-saving idea of using Dock for imitation of switch position.
 
Well,
1) base.OnPaint is redundant in this case,
2) a setter for ColorToggleOn and all similar property setters should always call Invalidate,
3) naming isON and isOFF violates good Microsoft naming conventions and is highly misleading; good API should have just one boolean property IsOn with both setter and getter; the interface should be pretty much the same as with Check Box
4) I would avoid Designer at all and derived the control from System.Windows.Forms.ContainerControl and did all layout in code; first, it would allow you to show all your code in this answer :-) and also you would avoid cumbersome of generated code; this is one of the many cases when Designer does not help, only demands; in code, you could easily make the control more flexible.
 
Overall, my 4.
 
Cheers,
--SA
TheCardinal at 23-Oct-12 1:35am
   
just mock this up in a few seconds in the designer to test my concept :D
how would you do this without using the designer? i want to make this a fullblown control :D
 
thanks for the feedback :D
Sergey Alexandrovich Kryukov at 23-Oct-12 1:59am
   
If you want to support designed by control, it's yes another reason to develop it fully in code. I mean development of control, not use of it. Isn't that obvious that Designer means tedious manual development, and only code helps to do everything without repeating yourself and other stupidities? Code is more for software developer, designer is more for ad-hoc users.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

Here's my quick contribution. This is a far more complete version of TheCardinal's code. This is all in code so you can add it to your project and it will show up in the designer's toolbox (no namespace - it'll be at the top). The default event is set so you can double-click the control and it will fill out a CheckChanged event handler for you. Colors, borders, and the ON/OFF label are customizable. It exposes a property called Checked just like a checkbox control.
 

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
 

//data for a change event. the current implementation
//guarantees OldValue and NewValue are always different,
//but the change event is built this way so you could change
//internal behavior if you wanted.

public class CheckChangedEventArgs : EventArgs
{
    public bool OldValue { get; set; }
    public bool NewValue { get; set; }
 
    public CheckChangedEventArgs(bool old_value, bool new_value)
    {
        NewValue = new_value;
        OldValue = old_value;
    }
}
 

//event handler
public delegate void CheckChangedEventHandler(object sender, CheckChangedEventArgs e);
 

 
[DefaultEvent("CheckChanged")]
public class ToggleSwitch : UserControl
{
    //internal variables and their defaults.
    private Color _ColorToggleOn = Color.Green;
    private Color _ColorToggleOff = Color.Red;
    private Color _ColorButtonOn = Color.Honeydew;
    private Color _ColorButtonOff = Color.Snow;
    private string _TextON = "ON";
    private string _TextOFF = "OFF";
    private bool _checked = false;
    private bool _BorderExtraThin = true;
    private bool _BorderForButton = true;
    private int _ButtonWidthPercentage = 30;
 
    //public properties that will show in the designer
    public Color ColorToggleOn { get { return _ColorToggleOn; } set { _ColorToggleOn = value;  UpdateColors(); } }
    public Color ColorToggleOff { get { return _ColorToggleOff; } set { _ColorToggleOff = value; UpdateColors(); } }    
    public Color ColorButtonOn { get { return _ColorButtonOn; } set { _ColorButtonOn = value; UpdateColors(); } }
    public Color ColorButtonOff { get { return _ColorButtonOff; } set { _ColorButtonOff = value; UpdateColors(); } }
    public string TextON { get { return _TextON; } set { _TextON = value; UpdateColors(); } }
    public string TextOFF { get { return _TextOFF; } set { _TextOFF = value; UpdateColors(); } }
    public bool BorderExtraThin { get { return _BorderExtraThin; } set { _BorderExtraThin = value; UpdateBorders(); UpdateColors(); Refresh(); } }
    public bool BorderForButton { get { return _BorderForButton; } set { _BorderForButton = value; UpdateBorders(); UpdateColors(); Refresh(); } }
    public int ButtonWidthPercentage { get { return _ButtonWidthPercentage; } set { _ButtonWidthPercentage = value; UpdateBorders(); UpdateColors(); Refresh(); } }
 
    public bool Checked
    {
        get { return _checked; }
 
        set
        {
            //This is set up so change events don't even occur unless the value is really changing.
            //This behavior could be modified if for some reason you want a change event without
            //  the value actually changing; which explains the CheckChangedEventArgs having a
            //  old value and a new value, even though the current implementation guarantees
            //  they are actually different.

            if (Checked == value)
                return;
 
            _checked = value;
            UpdateColors();
 
            CheckChanged(this, new CheckChangedEventArgs(!Checked, Checked));
        }
    }
    
    //we use a floating label control as the "button" and optional text.
    private Label label1;
 
    //CheckChanged is the default event for this control, and the only custom one we need.
    [Category("Action")]
    [Description("Fires when the switch is toggled, just like a checkbox")]
    public event CheckChangedEventHandler CheckChanged;
 
    void _CheckChangedDoNothing(object sender, CheckChangedEventArgs e)
    {
    }
 
    public ToggleSwitch()
    {
        CheckChanged = new CheckChangedEventHandler(_CheckChangedDoNothing);
 
        label1 = new Label();
        label1.ForeColor = this.ForeColor;
        label1.Visible = true;
        label1.TextAlign = ContentAlignment.MiddleCenter;
        label1.BorderStyle = BorderStyle.FixedSingle;
        label1.MouseDown += new MouseEventHandler(label1_MouseDown);
            
        this.Controls.Add(label1);
 
        UpdateColors();
    }
 
    void label1_MouseDown(object sender, EventArgs e)
    {
        Clicked();
    }
 
    protected override void OnMouseDown(MouseEventArgs e)
    {
        base.OnMouseDown(e);
        Clicked();
    }
 
    private void Clicked()
    {
        Checked = !Checked;
    }
 
    private void UpdateBorders()
    {
        if (BorderExtraThin)
        {
            BorderStyle = System.Windows.Forms.BorderStyle.None;
        }
 
        if (BorderForButton)
        {
            label1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        }
    }
 
    private void UpdateColors()
    {
        if (Checked)
        {
            this.BackColor = ColorToggleOn;
            this.label1.Dock = DockStyle.Right;
            label1.Width = (ClientRectangle.Width * ButtonWidthPercentage) / 100;
            this.label1.Text = TextON;
            this.label1.BackColor = ColorButtonOn;
 
            //not sure why but it seems to need a 1-px offset to look correct
            this.label1.Padding = new Padding(1, 0, 0, 0);
 

            this.Refresh();
        }
        else
        {
            this.BackColor = ColorToggleOff;
            this.label1.Dock = DockStyle.Left;
            label1.Width = (ClientRectangle.Width * ButtonWidthPercentage) / 100;
            this.label1.Text = TextOFF;
            this.label1.BackColor = ColorButtonOff;
 
            this.Refresh();
        }
    }
 
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
 
        int BORDER_SIZE = 1;
 
        if (BorderExtraThin)
        {
            ControlPaint.DrawBorder(e.Graphics, ClientRectangle,
                Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
                Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
                Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset,
                Color.Black, BORDER_SIZE, ButtonBorderStyle.Inset);
        }
    }
}
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

I simply ended up using a customized picture box with on and off switch state images. It's a quick and dirty hack, but it works. I may eventually end up modifying it to add other images.
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 304
1 Maciej Los 285
2 Sergey Alexandrovich Kryukov 230
3 Shweta N Mishra 186
4 Aajmot Sk 153
0 OriginalGriff 7,660
1 Sergey Alexandrovich Kryukov 7,072
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,760


Advertise | Privacy | Mobile
Web03 | 2.8.1411023.1 | Last Updated 11 Oct 2014
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100