ToolStripで複数のボタン(ToolStripButton)のチェック状態を排他制御する際、連続クリックしても選択状態が解除されないようにする

チェック状態の排他処理ができた!と感動してカチカチしていたら、連続クリックしたらチェック状態外れたやんけ・・・。というのを見つけたのでその対処を残しておきます。

伝わらないイメージ

f:id:sutefu7:20200227110352p:plain

サンプルソース

using System;
using System.Data;
using System.Linq;
using System.Windows.Forms;

/*
 * ToolStrip
 *   ToolStripButton, CheckOnClick = true, Checked = false, DisplayStyle = ImageAndText, Name = toolStripButton1
 *   ToolStripButton, CheckOnClick = true, Checked = false, DisplayStyle = ImageAndText, Name = toolStripButton2
 *   ToolStripButton, CheckOnClick = true, Checked = false, DisplayStyle = ImageAndText, Name = toolStripButton3
 * 
 *  チェック状態の排他制御は、CheckedChanged ではなく Click イベントで処理します。
 *  連続クリックのチェック外れちゃう対策は、前回のチェック状態を見て処理します。
 */

namespace WindowsFormsApp39
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            var btn = sender as ToolStripButton;
            if (isChecked1 && !btn.Checked)
            {
                btn.Checked = true;
                return;
            }

            if (btn.Checked)
                CommonToolStripButton_Click(sender, e);
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            var btn = sender as ToolStripButton;
            if (isChecked2 && !btn.Checked)
            {
                btn.Checked = true;
                return;
            }

            if (btn.Checked)
                CommonToolStripButton_Click(sender, e);
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            var btn = sender as ToolStripButton;
            if (isChecked3 && !btn.Checked)
            {
                btn.Checked = true;
                return;
            }

            if (btn.Checked)
                CommonToolStripButton_Click(sender, e);
        }


        private bool isChecked1 = false;
        private bool isChecked2 = false;
        private bool isChecked3 = false;

        private void CommonToolStripButton_Click(object sender, EventArgs e)
        {
            var checkedButton = sender as ToolStripButton;
            var others = toolStrip1.Items.OfType<ToolStripButton>().Where(x => x != checkedButton);

            // チェックを付けたボタン以外は、チェックを外す
            foreach (var other in others)
                other.Checked = false;

            // 今回分の状態を保持しておく
            isChecked1 = false;
            isChecked2 = false;
            isChecked3 = false;

            switch (checkedButton.Name)
            {
                case "toolStripButton1": isChecked1 = true; break;
                case "toolStripButton2": isChecked2 = true; break;
                case "toolStripButton3": isChecked3 = true; break;
            }
        }
    }
}