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

发布于 2024-12-11 18:02:44 字数 1949 浏览 0 评论 0原文

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

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

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()之前,所以返回的控件列表当然是空的。卫生部!感谢您的所有回复。我很抱歉浪费了大家的时间。 :-(

I have a WinForms app that contains many NumericUpDown controls. In a nutshell, if my users enter a value into the control and then delete the text, I want to restore it (the text) when the control loses focus. So I decided that I'd check .Text when the control loses focus and if it's empty, I set .Text = .Value.ToString().

I'm doing this in the Leave event handler and it works just fine. But as I said, I have many of these controls (18, to be exact). I don't like creating 18 Leave event handlers that all do the same thing so I created a generic one like this:

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

I started to hook up all of the controls to this generic event handler but I quickly got tired of doing this:

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

So I thought I'd create a function that would return a list of all the controls of a specified type and then loop through that list and hookup the event handlers. That function looks like this:

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;
}

I call the function like this:

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

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

When I run my app, however, I don't see the expected behavior that occurs when I manually hookup each control to the generic event handler. This code is currently in the constructor of my form and I've tried calling it before as well as after the call to InitializeComponent() but neither one seems to be working. I get no error of any kind, I just don't see the behavior that I was expecting. I have a breakpoint set inside the generic event handler but the debugger never breaks so it seems like the event handler isn't being hooked up correctly. Does anyone know why this might be or how I can troubleshoot it further? Thanks!

EDIT

I just realized that the call to:

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

was happening before the call to InitializeComponent() so of course the list of controls being returned was empty. DOH! Thanks for all the replys. I apologize for wasting everyones time. :-(

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城花音 2024-12-18 18:02:44

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

You're passing this to your method, which is presumably a reference to your form. Your method will only catch the controls that are placed directly on your form. Any NumericUpDown controls that are not directly on the form (i.e. they're sitting on a panel or something) will be missed.

半衾梦 2024-12-18 18:02:44

为什么不创建一个包含 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 控件本身上。

Why not create a user control that has a NumericUpDown control in it.

Then handle this is in the user control events.

This worked for me:

 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);
            }
        }

Just note that the Leave event is on the user control not on the updown control itself.

箹锭⒈辈孓 2024-12-18 18:02:44

问题得到解答。请参阅上面的编辑。感谢 bsegraves 为我指明了正确的方向。

Question answered. See Edit above. Thanks to bsegraves for pointing me in the right direction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文