C# 单击 winform 应用程序中的按钮后,如何将焦点返回到上次使用的控件?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/37317/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you return the focus to the last used control after clicking a button in a winform app?
提问by Joe Barone
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#),其中用户在窗体中输入数据。在编辑表单中的数据时,用户可以随时单击表单上的按钮之一来执行某些操作。默认情况下,焦点会转到单击的按钮上,因此用户必须重新单击要编辑的控件才能继续修改表单上的数据。我需要做的是在处理按钮单击事件后将焦点返回到最后编辑的控件。这是一个示例屏幕截图,说明了我在说什么:
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 方法。然后,当单击按钮时,焦点将返回到单击按钮之前具有焦点的控件。有人对此有更优雅的解决方案吗?
采纳答案by Joshua Turner
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).
那么您不必担心手动装饰每个文本框(或忘记一个)。
回答by Jon Limjap
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.
我有兴趣首先找出您为什么要这样做。
回答by Ethan Gunderson
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.
我认为你所做的很好。我能想到的唯一改进方法是在访问每个控件时将它们存储到堆栈中。这将为您提供访问内容的完整时间线。
回答by Dan Herbert
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 GotFocuslistener 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
}
回答by Joe Barone
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 流畅。
回答by Joe Barone
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.
将按钮更改为标签并使其看起来像按钮。标签永远不会获得焦点,您不必进行所有额外的编码。
回答by Denis
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.
创建一个继承自 TextBox 的名为 CustomTextBox 的类。它有一个称为堆栈的静态变量。当文本框失去焦点时,推送到堆栈上。当您想找到最后一个焦点控件时,只需从堆栈中弹出第一个项目。确保清除静态 Stack 变量。