将通用事件处理程序连接到同一类型的多个控件

时间:2011-10-21 14:18:25

标签: c# winforms event-handling generic-handler

我有一个包含许多NumericUpDown控件的WinForms应用程序。简而言之,如果我的用户在控件中输入一个值然后删除文本,我想在控件失去焦点时恢复它(文本)。所以我决定在控件失去焦点时检查.Text,如果它是空的,我设置.Text = .Value.ToString()。

我在Leave事件处理程序中执行此操作,它运行正常。但正如我所说,我有很多这些控件(准确地说是18)。我不喜欢创建18个Leave事件处理程序,它们都做同样的事情所以我创建了一个像这样的通用处理程序:

private void numericUpDown_GenericLeave(object sender, EventArgs e)
{
    if (string.IsNullOrEmpty(((NumericUpDown)sender).Text))
        ((NumericUpDown)sender).Text = ((NumericUpDown)sender).Value.ToString();
}

我开始将所有控件连接到这个通用事件处理程序,但我很快厌倦了这样做:

numericUpDown1.Leave += numericUpDown_GenericLeave;
numericUpDown2.Leave += numericUpDown_GenericLeave;
numericUpDown3.Leave += numericUpDown_GenericLeave;
...
numericUpDown18.Leave += numericUpDown_GenericLeave;

所以我想我会创建一个函数来返回指定类型的所有控件的列表,然后遍历该列表并连接事件处理程序。该功能如下所示:

public static List<Control> GetControlsOfSpecificType(Control container, Type type)
{
    var controls = new List<Control>();

    foreach (Control ctrl in container.Controls)
    {
        if (ctrl.GetType() == type)
            controls.Add(ctrl);

        controls.AddRange(GetControlsOfSpecificType(ctrl, type));
    }

    return controls;
}

我这样称呼函数:

var listOfControls = GetControlsOfSpecificType(this, typeof(NumericUpDown));

foreach (var numericUpDownControl in listOfControls)
{
    numericUpDownControl.Leave += numericUpDown_GenericLeave;
}

然而,当我运行我的应用程序时,我没有看到当我手动将每个控件连接到通用事件处理程序时发生的预期行为。这段代码目前在我的表单的构造函数中,我已经尝试过调用它以及调用InitializeComponent()之后,但似乎没有一个工作。我没有任何错误,我只是没有看到我期待的行为。我在通用事件处理程序中设置了断点,但调试器永远不会中断,所以看起来事件处理程序没有正确连接。有谁知道为什么会这样或我如何进一步解决它?谢谢!

修改

我刚刚意识到要求:

var listOfControls = GetControlsOfSpecificType(this, typeof(NumericUpDown));

在调用InitializeComponent()之前发生了,所以返回的控件列表当然是空的。 DOH!感谢所有的回复。我为浪费每个人的时间而道歉。 : - (

3 个答案:

答案 0 :(得分:1)

您正在将this传递给您的方法,这可能是您form的引用。您的方法只会捕获直接放在表单上的控件。不会直接在表单上的任何NumericUpDown控件(即它们坐在面板上或其他东西上)都将被遗漏。

答案 1 :(得分:1)

为什么不创建一个包含NumericUpDown控件的用户控件。

然后处理这是在用户控件事件中。

这对我有用:

 private decimal _previous = 0;

  private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            if (((NumericUpDown)sender).Text.Length > 0)
            {
                _previous = this.numericUpDown1.Value;
            }
        }

        private void UserControl1_Leave(object sender, EventArgs e)
        {
            if (this.numericUpDown1.Text == "")
            {
                this.numericUpDown1.Value = _previous;
                this.numericUpDown1.Text = System.Convert.ToString(_previous);
            }
        }

请注意,Leave事件在用户控件上,而不是在updown控件本身上。

答案 2 :(得分:0)

问题回答。见上面的编辑。感谢bsegraves指出我正确的方向。