单击winform应用程序中的按钮后,如何将焦点返回到上次使用的控件?

时间:2022-10-20 10:51:14

I'm working on a windows forms application (C#) where a user is entering data in a form. At any point while editing the data in the form the user can click one of the buttons on the form to perform certain actions. By default the focus goes to the clicked button so the user has to click back on to the control they want to edit in order to continue modifying the data on the form. What I need to be able to do is return the focus to the last edited control after the button click event has been processed. Here's a sample screenshot that illustrates what I'm talking about:

我正在使用Windows窗体应用程序(C#),用户在表单中输入数据。在编辑表单中的数据时,用户可以单击表单上的其中一个按钮来执行某些操作。默认情况下,焦点转到单击的按钮,因此用户必须单击返回要编辑的控件才能继续修改表单上的数据。我需要做的是在处理完按钮点击事件后将焦点返回到最后编辑的控件。这是一个示例截图,说明了我在说什么:

单击winform应用程序中的按钮后,如何将焦点返回到上次使用的控件?

The user can be entering data in textbox1, textbox2, textbox3, etc and click the button. I need the button to return the focus back to the control that most recently had the focus before the button was clicked.

用户可以在textbox1,textbox2,textbox3等中输入数据,然后单击按钮。我需要按钮将焦点返回到最近在单击按钮之前具有焦点的控件。

I'm wondering if anyone has a better way of implementing this functionality than what I've come up with. Here's what I'm doing right now:

我想知道是否有人比我想出的更好地实现这个功能。这就是我现在正在做的事情:

   public partial class Form1 : Form
    {
        Control _lastEnteredControl;

        private void textBox_Enter(object sender, EventArgs e)
        {
            _lastEnteredControl = (Control)sender;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Do something here");
            _lastEnteredControl.Focus();
        }


    }

So basically what we have here is a class variable that points to the last entered control. Each textbox on the form is setup so the textBox_Enter method is fired when the control receives the focus. Then, when the button is clicked focus is returned to the control that had the focus before the button was clicked. Anybody have any more elegant solutions for this?

所以我们这里基本上是一个指向最后输入控件的类变量。表单上的每个文本框都已设置,因此当控件获得焦点时会触发textBox_Enter方法。然后,当单击该按钮时,焦点将返回到单击按钮之前具有焦点的控件。有人有更优雅的解决方案吗?

7 个解决方案

#1


16  

For a bit of 'simplicity' maybe try.

对于一点'简单'可能会尝试。

public Form1()
    {
        InitializeComponent();

        foreach (Control ctrl in Controls)
        {
            if (ctrl is TextBox)
            {
                ctrl.Enter += delegate(object sender, EventArgs e)
                              {
                                  _lastEnteredControl = (Control)sender;
                              };
            }
        }
    }

then you don't have to worry about decorating each textbox manually (or forgetting about one too).

那么你不必担心手动装饰每个文本框(或者忘记一个文本框)。

#2


2  

You could do the following

您可以执行以下操作

Change the button to a label and make it look like a button. The label will never get focus and you don't have to do all the extra coding.

将按钮更改为标签,使其看起来像一个按钮。标签永远不会聚焦,您不必进行所有额外编码。

#3


1  

I think what you're doing is fine. The only thing I could think of to improve it would be to store each control into a stack as they are accessed. That would give you a complete time line of what was accessed.

我觉得你做的很好。我唯一能想到的就是在访问它们时将每个控件存储到一个堆栈中。这将为您提供完整的访问时间。

#4


1  

Your approach looks good. If you want to avoid having to add an the event handler to every control you add, you could create a recursive routine to add a GotFocus listener to every control in your form. This will work for any type of control in your form, however you could adjust it to meet your needs.

你的方法很好看。如果要避免必须为添加的每个控件添加事件处理程序,可以创建一个递归例程,将GotFocus侦听器添加到表单中的每个控件。这适用于表单中的任何类型的控件,但您可以调整它以满足您的需要。

private void Form_OnLoad(object obj, EventArgs e)
{
    AddGotFocusListener(this);
}

private void AddGotFocusListener(Control ctrl)
{
    foreach(Control c in ctrl.Controls)
    {
        c.GotFocus += new EventHandler(Control_GotFocus);
        if(c.Controls.Count > 0)
        {
            AddGotFocusListener(c);
        }
    }
}

private void Control_GotFocus(object obj, EventArgs e)
{
    // Set focused control here
}

#5


0  

Your implementation looks good enough -- what I do want to know is why you want to do this in the first place? Won't it be preferrable for the focus to cycle back to the first entry? Is the data in the last text box so malleable that once they click the button it is "remembered"? Or do you have some sort of operation that the button does to that specifici text box data -- in that case shouldn't the focus go to a subsequent control instead?

你的实现看起来很好 - 我想知道的是你为什么要首先做这个?焦点重新回到第一个条目不是更好吗?最后一个文本框中的数据是否具有可塑性,一旦他们点击按钮就会“记住”?或者你有一些按钮对特定文本框数据执行的操作 - 在这种情况下,焦点不应该转移到后续控件吗?

I'm interested in finding out why you want to do this in the first place.

我很想知道你为什么要这样做。

#6


0  

Yeah, I admit the requirement is a bit unusual. Some of the information that the users will be entering into this application exists in scans of old documents that are in a couple of different repositories. The buttons facilitate finding and opening these old docs. It's difficult to predict where the users will be on the form when they decide to pull up a document with more information to enter on the form. The intent is to make the UI flow well in spite of these funky circumstances.

是的,我承认这个要求有点不寻常。用户将进入此应用程序的一些信息存在于扫描几个不同存储库中的旧文档中。按钮有助于查找和打开这些旧文档。当用户决定提取包含更多信息的文档进入表单时,很难预测用户在表单上的位置。尽管存在这些时髦的情况,但目的是使UI流畅。

#7


0  

Create a class called CustomTextBox that inherits from TextBox. It has a static variable called stack. When the textbox loses focus push onto the stack. When you want to find the last focused control then just pop the first item from the stack. Make sure to clear the static Stack variable.

创建一个名为CustomTextBox的类,该类继承自TextBox。它有一个名为stack的静态变量。当文本框失去焦点时,推入堆栈。当您想要找到最后一个聚焦控件时,只需从堆栈中弹出第一个项目。确保清除静态Stack变量。

#1


16  

For a bit of 'simplicity' maybe try.

对于一点'简单'可能会尝试。

public Form1()
    {
        InitializeComponent();

        foreach (Control ctrl in Controls)
        {
            if (ctrl is TextBox)
            {
                ctrl.Enter += delegate(object sender, EventArgs e)
                              {
                                  _lastEnteredControl = (Control)sender;
                              };
            }
        }
    }

then you don't have to worry about decorating each textbox manually (or forgetting about one too).

那么你不必担心手动装饰每个文本框(或者忘记一个文本框)。

#2


2  

You could do the following

您可以执行以下操作

Change the button to a label and make it look like a button. The label will never get focus and you don't have to do all the extra coding.

将按钮更改为标签,使其看起来像一个按钮。标签永远不会聚焦,您不必进行所有额外编码。

#3


1  

I think what you're doing is fine. The only thing I could think of to improve it would be to store each control into a stack as they are accessed. That would give you a complete time line of what was accessed.

我觉得你做的很好。我唯一能想到的就是在访问它们时将每个控件存储到一个堆栈中。这将为您提供完整的访问时间。

#4


1  

Your approach looks good. If you want to avoid having to add an the event handler to every control you add, you could create a recursive routine to add a GotFocus listener to every control in your form. This will work for any type of control in your form, however you could adjust it to meet your needs.

你的方法很好看。如果要避免必须为添加的每个控件添加事件处理程序,可以创建一个递归例程,将GotFocus侦听器添加到表单中的每个控件。这适用于表单中的任何类型的控件,但您可以调整它以满足您的需要。

private void Form_OnLoad(object obj, EventArgs e)
{
    AddGotFocusListener(this);
}

private void AddGotFocusListener(Control ctrl)
{
    foreach(Control c in ctrl.Controls)
    {
        c.GotFocus += new EventHandler(Control_GotFocus);
        if(c.Controls.Count > 0)
        {
            AddGotFocusListener(c);
        }
    }
}

private void Control_GotFocus(object obj, EventArgs e)
{
    // Set focused control here
}

#5


0  

Your implementation looks good enough -- what I do want to know is why you want to do this in the first place? Won't it be preferrable for the focus to cycle back to the first entry? Is the data in the last text box so malleable that once they click the button it is "remembered"? Or do you have some sort of operation that the button does to that specifici text box data -- in that case shouldn't the focus go to a subsequent control instead?

你的实现看起来很好 - 我想知道的是你为什么要首先做这个?焦点重新回到第一个条目不是更好吗?最后一个文本框中的数据是否具有可塑性,一旦他们点击按钮就会“记住”?或者你有一些按钮对特定文本框数据执行的操作 - 在这种情况下,焦点不应该转移到后续控件吗?

I'm interested in finding out why you want to do this in the first place.

我很想知道你为什么要这样做。

#6


0  

Yeah, I admit the requirement is a bit unusual. Some of the information that the users will be entering into this application exists in scans of old documents that are in a couple of different repositories. The buttons facilitate finding and opening these old docs. It's difficult to predict where the users will be on the form when they decide to pull up a document with more information to enter on the form. The intent is to make the UI flow well in spite of these funky circumstances.

是的,我承认这个要求有点不寻常。用户将进入此应用程序的一些信息存在于扫描几个不同存储库中的旧文档中。按钮有助于查找和打开这些旧文档。当用户决定提取包含更多信息的文档进入表单时,很难预测用户在表单上的位置。尽管存在这些时髦的情况,但目的是使UI流畅。

#7


0  

Create a class called CustomTextBox that inherits from TextBox. It has a static variable called stack. When the textbox loses focus push onto the stack. When you want to find the last focused control then just pop the first item from the stack. Make sure to clear the static Stack variable.

创建一个名为CustomTextBox的类,该类继承自TextBox。它有一个名为stack的静态变量。当文本框失去焦点时,推入堆栈。当您想要找到最后一个聚焦控件时,只需从堆栈中弹出第一个项目。确保清除静态Stack变量。