8

I'd like to have a toolstrip with some buttons on it (WinFroms/c#/.net4). I'd like to have the clicked button be checked and all others unchecked, so I want to have only the clicked button checked, all the others unchecked.

I know toolstrip button has checkedonlclick property, but when I click one button, others may be also checked. In good old VB6 there was an automatic solution for this problem: buttongroup on toolbar. Is there any similar in Winfoms?

Or should I handle it from code?! Switch all other buttons to unchecked state when one button is checked? If so, then it would not be my favourite solution...

ekad
  • 14,436
  • 26
  • 44
  • 46
Tom
  • 3,899
  • 22
  • 78
  • 137

4 Answers4

12

Call this code on the toolStripButton_Click events and you should get the desired result.

   foreach (ToolStripButton item in ((ToolStripButton)sender).GetCurrentParent().Items)
   {
       if (item == sender) item.Checked = true;
       if ((item != null) && (item != sender))
       {
          item.Checked = false;
       }
   }
secretformula
  • 6,414
  • 3
  • 33
  • 56
KreepN
  • 8,528
  • 1
  • 40
  • 58
  • Thx, I know that...I thought there was a more straightforward solution for toolstrip... – Tom Jun 17 '11 at 20:28
3

I guess this is an old question, however I was looking for a solution to this problem as well and ended up making a kind of ToolStripRadioButton by extending ToolStripButton. The behaviour should be the same as a normal radio button, as far as I can see. I have however added a group id to make it possible to have multiple radio button groups within the same toolstrip.

One can add the radio button to a toolstrip like a normal ToolStripButton:

Add RadioButton

To make the button stand more out when checked I have given it a gradient background (CheckedColor1 to CheckedColor2 from top to bottom):

Checked RadioButton gradient background

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;

public class ToolStripRadioButton : ToolStripButton
{
    private int radioButtonGroupId = 0;
    private bool updateButtonGroup = true;

    private Color checkedColor1 = Color.FromArgb(71, 113, 179);
    private Color checkedColor2 = Color.FromArgb(98, 139, 205);

    public ToolStripRadioButton()
    {
        this.CheckOnClick = true;
    }

    [Category("Behavior")]
    public int RadioButtonGroupId
    {
        get 
        { 
            return radioButtonGroupId; 
        }
        set
        {
            radioButtonGroupId = value;

            // Make sure no two radio buttons are checked at the same time
            UpdateGroup();
        }
    }

    [Category("Appearance")]
    public Color CheckedColor1
    {
        get { return checkedColor1; }
        set { checkedColor1 = value; }
    }

    [Category("Appearance")]
    public Color CheckedColor2
    {
        get { return checkedColor2; }
        set { checkedColor2 = value; }
    }

    // Set check value without updating (disabling) other radio buttons in the group
    private void SetCheckValue(bool checkValue)
    {
        updateButtonGroup = false;
        this.Checked = checkValue;
        updateButtonGroup = true;
    }

    // To make sure no two radio buttons are checked at the same time
    private void UpdateGroup()
    {
        if (this.Parent != null)
        {
            // Get number of checked radio buttons in group
            int checkedCount = this.Parent.Items.OfType<ToolStripRadioButton>().Count(x => x.RadioButtonGroupId == RadioButtonGroupId && x.Checked);

            if (checkedCount > 1)
            {
                this.Checked = false;
            }
        }
    }

    protected override void OnClick(EventArgs e)
    {
        base.OnClick(e);
        this.Checked = true;
    }

    protected override void OnCheckedChanged(EventArgs e)
    {
        if (this.Parent != null && updateButtonGroup)
        {
            foreach (ToolStripRadioButton radioButton in this.Parent.Items.OfType<ToolStripRadioButton>())
            {
                // Disable all other radio buttons with same group id
                if (radioButton != this && radioButton.RadioButtonGroupId == this.RadioButtonGroupId)
                {
                    radioButton.SetCheckValue(false);
                }
            }
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        if (this.Checked)
        {
            var checkedBackgroundBrush = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height), CheckedColor1, CheckedColor2);
            e.Graphics.FillRectangle(checkedBackgroundBrush, new Rectangle(new Point(0, 0), this.Size));
        }

        base.OnPaint(e);
    }
}

Perhaps useful to others as well.

Roger Saele
  • 177
  • 2
  • 10
1

I'm not aware of a way to do this in the designer, but it's fairly simple to do in code:

readonly Dictionary<string, HashSet<ToolStripButton>> mButtonGroups;

...

ToolStripButton AddGroupedButton(string pText, string pGroupName) {
   var newButton = new ToolStripButton(pText) {
      CheckOnClick = true
   };

   mSomeToolStrip.Items.Add(newButton);

   HashSet<ToolStripButton> buttonGroup;
   if (!mButtonGroups.TryGetValue(pGroupName, out buttonGroup)) {
      buttonGroup = new HashSet<ToolStripButton>();
      mButtonGroups.Add(pGroupName, buttonGroup);
   }

   newButton.Click += (s, e) => {
      foreach (var button in buttonGroup)
         button.Checked = button == newButton;
   };

   return newButton;
}
Dave Cousineau
  • 12,154
  • 8
  • 64
  • 80
-2

I haven't done it in a little but if you use a group box around radio buttons it will only allow one to be checked at a time.

apaq11
  • 82
  • 2