我想在更改状态之前验证radiobutton,但是当焦点离开控件时它确实会触发

时间:2016-02-07 23:45:03

标签: c# winforms radio-button

我有一个简单的Winform示例,演示了会发生什么。

有一个带有两个RadioButtons的GroupBox。这两个按钮共享一个验证事件处理程序。表单上还有一个什么都不做的Button。没有连接任何事件。最后,有一个CheckBox控制传递验证的状态。检查通过并取消选中它失败。

当程序启动并且用户点击RadioButton时,验证事件不会触发。然后当我点击当前按钮以外的任何控件时,验证事件将触发。 NOP按钮让我可以点击CheckBox旁边的东西。

在此测试中,CheckBox表示传递验证的状态。

这不起作用,因为一旦我取消选中CheckBox然后单击单选按钮,焦点就会永远停滞不前。您无法将焦点集中到CheckBox以更改其状态。

原因是在焦点离开时始终调用Validating事件,而不是在单击RadioButton时调用。它看到“valdating”失败并取消该事件。

这显然是错误的做法。在初次点击时我应该做些什么来测试? Click事件在状态发生变化后发生。

我应该使用什么事件以便在更改RadioButton状态之前测试验证?然后,我可以在再次尝试之前离开按钮并解决问题。

这个例子是一个显示我死路的简化测试。我的真实世界的例子是两个RadioButtons选择DataGridView中两个相似表中的一个。这两个表是相关的,我希望它们在同一个TabPage上。当用户选择备用表时,我想在切换之前进行验证/确认。如果确认失败,我想取消单选按钮。

// Validate is called when the radio button is clicked and when it leaves the box
using System.ComponentModel;
using System.Windows.Forms;

namespace ValidateRadioButton
{
  public partial class Form1 : Form
  {
    int count;
    public Form1()
    {
      InitializeComponent();
    }

    private void radiobutton_Validating(object sender, CancelEventArgs e)
    {
      if (sender is RadioButton) {
        // If box not checked, cancel radioButton change
        // This becomes a Hotel California test, once unchecked you 
        // can never leave the control
        e.Cancel = !chkAllowChange.Checked;
      }
      count++;
      //Display the number of times validating is called in the title bar
      //Demonstrates when the event is called
      Text = count.ToString(); 
    }

  }
}

2 个答案:

答案 0 :(得分:0)

我已经在测试项目中复制了您的表单,我想我知道发生了什么。

Checked的{​​{1}}属性设置为true将阻止任何控件设置它失去焦点,直到输入被“纠正”。如您所知,只要控件失去焦点,就会触发CancelEventArgs事件。用户变得“卡住”,因为他们可以“纠正”他们的输入的唯一方法是修改复选框,由于点击单选按钮上的Validating事件,他们无法访问。

我提出的解决方案是将Validating事件移至Validated,而不是单选按钮:

GroupBox

请务必从单选按钮 删除 private void groupBox_Validating(object sender, CancelEventArgs e) { if (sender is RadioButton) { e.Cancel = !checkBox1.Checked; } count++; //Display the number of times validating is called in the title bar //Demonstrates when the event is called Text = count.ToString(); } 事件处理程序。

为清楚起见,我已经以这种方式设置了表格:

Screenshot of layout of form controls, within group box.

现在结果是我无法点击“确定”直到我勾选了复选框。我保留了您的Validating作业,以便您可以看到表单现在只调用Text = count.ToString()

答案 1 :(得分:0)

我最终使用RadioButtons的CheckChangedClick事件。

我跟踪当前有效的RadioButton并在CheckChanged事件中进行验证。然后在Click事件中,如果验证失败,我将恢复之前的活动RadioButton。否则我们可以继续使用RadioButton。

此解决方案适用于组中的两个或多个RadioButton,并且在使用键盘时可以正常工作。

using System.ComponentModel;
using System.Windows.Forms;

namespace ValidateRadioButton
{
  public partial class Form1 : Form
  {

    // RadioButton that is currently active
    RadioButton ActiveRadioButton;
    bool cancelingChange;

    public Form1()
    {
      InitializeComponent();
      activeRadioButton = this.radioButton1;
    }

    private void radioButton_CheckedChanged(object sender, System.EventArgs e)
    {
      // Each click fires two events
      // One for the RadioButton loosing its check and the other that is gaining it
      // We are interested in the one gaining it
      if (sender is RadioButton) {
        RadioButton radioButton = (RadioButton)sender;
        if (radioButton.Checked) {
          // If this button is changing because of a canceled check
          // do not validate
          if (!cancelingChange) {
            cancelingChange = !ValidateData();
            if (!cancelingChange) {
              // Mark this as the active value
              activeRadioButton = radioButton;
            }
          }
        }
      }
    }

    private void radioButton_Click(object sender, System.EventArgs e)
    {
      // This is called after the RadioButton has changed
      if (cancelingChange) {
        // Check theRadioButton that was previously checked
        activeRadioButton.Checked = true;
        cancelingChange = false;
      }
      else {
        // Do the thing the RadioButton should do
        // If using separate events they all must start with the condition above.
        this.Text = ((RadioButton)sender).Name;
      }
    }

    /// <summary>
    /// Validate state of data
    /// </summary>
    /// <returns></returns>
    private bool ValidateData()
    {
      bool result = chkAllowChange.Checked;
      if (!result) {
        result = MessageBox.Show("Do you want to save your data?", "CheckBox unchecked", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK;
        if (result) {
          // This is where I would save the data
          chkAllowChange.Checked = true;
        }
      }
      return result;
    }
  }
}
相关问题