简体   繁体   English

如何在C#中的表单上的文本框之间切换?

[英]How do I tab between text boxes on a form in C#?

I'm trying to get the functionality to tab to the next text box once the user has input their data for the previous text box. 一旦用户输入了上一个文本框的数据,我就会尝试将功能切换到下一个文本框。 For example, once they filled in a company name I'd like to be able to hit Tab and set the focus on the next text box "Job Name". 例如,一旦他们填写了公司名称,我希望能够点击Tab并将焦点放在下一个文本框“ Job Name”上。 Is this done in the code or the form properties? 这是在代码或表单属性中完成的吗?

Here is some of my code. 这是我的一些代码。 I'm unsure how to nest a KeyEventsArgs within these, which is how I've seen others set the focus to the next text boxes using the KeyPress function. 我不确定如何在其中嵌套KeyEventsArgs ,这就是我看到其他人使用KeyPress函数将焦点设置到下一个文本框的方式。

private void textBox1_TextChanged(object sender, EventArgs e)
{
    CompanyName = textBox1.Text;
    textBox1.AcceptsTab = true;
}

private void textBox2_TextChanged(object sender, EventArgs e)
{
    JobName = textBox2.Text;
    textBox2.AcceptsTab = true;
}

From the question you've asked and the code sample provided, there seems to be somewhat of a disconnect between your approach and the desired functionality. 从您提出的问题和提供的代码示例来看,您的方法与所需功能之间似乎有些脱节。

As you would like the user to be able to use the Tab key in order to shift keyboard focus between elements in the window, you need only provide a TabIndex attribute on each of your TextBox controls. 因为您希望用户能够使用Tab键来在窗口中的元素之间切换键盘焦点,所以您只需要在每个TextBox控件上提供一个TabIndex属性。 There is no need to use the TextChanged events to achieve this and it can be done completely in XAML for simplicity's sake. 无需使用TextChanged事件即可实现此目的,为简便起见,它可以完全在XAML中完成。

From how I interpret your question, your next follow-on will likely be: 根据我对您问题的理解,您的下一个后续步骤可能是:

How do I initially give focus to a control when the application starts? 应用程序启动时,最初如何将焦点集中在控件上?

To address this, there are a couple of alternatives available, simplest of which comes in the form of the FocusManager, which again I've illustrated usage of in XAML. 为了解决这个问题,有几种可用的替代方法,其中最简单的是FocusManager的形式,我再次说明了XAML中的用法。

For convenience, here is a XAML-only implementation with TabIndex and FocusManager implemented: 为方便起见,这是仅XAML的实现,其中实现了TabIndex和FocusManager:

<Window x:Class="tab_navigation.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:tab_navigation"
    mc:Ignorable="d"
    Title="MainWindow" ResizeMode="NoResize" SizeToContent="WidthAndHeight" FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName}">
<Grid Margin="10">
    <StackPanel Orientation="Vertical">
        <StackPanel Orientation="Vertical" Margin="0,0,0,10">
            <Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" />
            <TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/>
        </StackPanel>
        <StackPanel Orientation="Vertical">
            <Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/>
            <TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/>
        </StackPanel>
    </StackPanel>

</Grid>

Give me a shout if you need any further help, although I would strongly recommend checking out some of the MSDN resources first, particularly those concerning Focus 如果您需要任何进一步的帮助,请给我喊一声,尽管我强烈建议您首先检查一些MSDN资源,尤其是那些与Focus有关的资源

UPDATE : In response to comment regarding implementing the solution, WPF has a different design and best practices from that of WinForms. 更新 :为了回应有关实施该解决方案的评论,WPF具有与WinForms不同的设计和最佳实践。 I would strongly make the case that you cease using Forms and instead use a Window or UserControl derived class in place of a Form in your WPF project unless there is a very, very good reason for doing so. 强烈建议您停止使用Forms,而在WPF项目中使用Window或UserControl派生类代替Form,除非有非常非常好的理由。 If you continue to use a Form inside of your WPF project, you will indeed need to implement your own keyboard navigation logic inside that form, and bridge various other gaps you'll inevitably run into when trying to get a Form behave in a commonly acceptable way. 如果继续在WPF项目中使用Form,则确实需要在该Form中实现自己的键盘导航逻辑,并弥合在尝试使Form表现为通常可接受的情况时不可避免地遇到的其他各种差距。方式。 I'll instead show you how you can achieve your request using an objectively better and more suitable approach in WPF-only, using Window or UserControl elements. 相反,我将向您展示如何使用Window或UserControl元素,在仅WPF中使用客观上更好,更合适的方法来实现您的请求。 There is also a complete solution zip downloadable here . 这里还有完整的解决方案zip可下载

WPF is by design a lot more modular than WinForms and splits the areas of concerns nicely by default, although most developers implement a design pattern ontop of this; WPF在设计上比WinForms模块化得多,并且默认情况下可以很好地拆分关注区域,尽管大多数开发人员都在此基础上实现了设计模式。 MVVM is the current darling of WPF, and does add quite a lot of value to a project, although it is outside the scope of your question, so I shall instead address the question itself on the grounds of how to achieve the request in its most basic forms. MVVM是WPF的当前宠儿,尽管确实超出了您的问题范围,但确实为项目增加了很多价值,因此我将根据如何最大程度地实现请求来解决问题本身。基本形式。 Do please be aware though that this is not the entirely ideal solution and I would strongly recommend you learn and implement the MVVM pattern for WPF if you are not already familiar with it. 请注意,尽管这不是完全理想的解决方案,但是如果您还不熟悉WPF,我强烈建议您学习和实现MVVM模式。

With that disclaimer out of the way, instead of using a Form in WPF , its more useful for us to make a class which derives from Window . 有了这样的免责声明,与其在WPF中使用Form,不如让它成为从Window派生的类更为有用。 An even more common scenario in WPF would be that you would want to have a single window whose content changes between different views, rather than say creating multiple windows, although again that is outside the scope of the question and would rely upon reading into Binding and MVVM. 在WPF中,更常见的情况是您希望拥有一个窗口,其内容在不同视图之间变化,而不是说创建多个窗口,尽管这再次超出了问题的范围,并且将依赖于阅读Binding和MVVM。 I'm going to be showing you a quick and easy way to get the functionality you've asked for, I'm just trying to iterate here that this is not the norm almost all of the time. 我将向您展示一种快速简便的方法来获得您所要求的功能,我只是想在这里反复说明这并不是几乎所有时间的规范

To make a working solution, do the following to your project: 要制定可行的解决方案,请对您的项目执行以下操作:

  1. Right click your project in the solution explorer (presuming you are using Visual Studio) 在解决方案资源管理器中右键单击您的项目(假定您正在使用Visual Studio)
  2. 'Add' a 'New Item...'. “添加”“新项目...”。
  3. Choose the 'Window (WPF)' template and name it. 选择“窗口(WPF)”模板并命名。 I'm going to call it CustomerInformationEntry from here out . 从这里开始,我将其命名为CustomerInformationEntry
  4. Open the CustomerInformationEntry.xaml file that has been created for us, remove the <Grid></Grid> tags and copy/paste this excerpt from the XAML I've already provided from above in their place: 打开为我们创建的CustomerInformationEntry.xaml文件, 删除 <Grid></Grid>标记,然后从上面已经提供的XAML位置复制/粘贴此摘录:

<Grid Margin="10"> <StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical" Margin="0,0,0,10"> <Label Content="Company Name:" Target="{Binding ElementName=TbxCompanyName}" /> <TextBox Name="TbxCompanyName" TabIndex="0" Width="160" HorizontalAlignment="Left"/> </StackPanel> <StackPanel Orientation="Vertical"> <Label Content="Job Description:" Target="{Binding ElementName=TbxJobDescription}"/> <TextBox Name="TbxJobDescription" TabIndex="1" Width="160" HorizontalAlignment="Left"/> </StackPanel> </StackPanel> </Grid>

  1. Add FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName} to the Window element in CustomerInformationEntry.xaml . FocusManager.FocusedElement="{Binding ElementName=TbxCompanyName}CustomerInformationEntry.xamlWindow元素中。
  2. This is our view or visual representation finished with now, and all that remains is to instanciate a new CustomerInformationEntry from our other Window or UserControl, and to then display it. 这是我们现在完成的视图或视觉表示,剩下的就是从我们其他的Window或UserControl实例化一个新的CustomerInformationEntry,然后显示它。 In this case I'm going to be putting a button onto the MainWindow.xaml , and providing it a click event which will create the instance of our new Window: 在这种情况下,我将在MainWindow.xaml上放置一个按钮,并为其提供一个click事件,该事件将创建新Window的实例:
    • In MainWindow.xaml add <Button Name="BtnOpenCustomerInformationEntry" Content="Enter Customer Information" Click="OpenCustomerInformationEntry"/> . MainWindow.xaml中,添加<Button Name="BtnOpenCustomerInformationEntry" Content="Enter Customer Information" Click="OpenCustomerInformationEntry"/> In my case I'll be adding the button inside my object, although you can put it wherever you like if you've already created your initial window. 就我而言,我将在对象内部添加按钮,尽管如果您已经创建了初始窗口,则可以将其放置在任意位置。
    • In MainWindow.xaml.cs we'll add a new private method which will be used by the Click event of your new button. MainWindow.xaml.cs中,我们将添加一个新的私有方法,该方法将由新按钮的Click事件使用。 Adding the following code: 添加以下代码:

private void OpenCustomerInformationEntry(object sender, RoutedEventArgs e) { CustomerInformationEntry myWindow = new CustomerInformationEntry(); myWindow.Show(); }

That's it, you now have a button in your MainWindow.xaml which when clicked uses the OpenCustomerInformationEntry method defined in MainWindow.xaml.cs, which in turn makes an instance of your CustomerInformationEntry window and displays it. 就是这样,您现在在MainWindow.xaml中有一个按钮,单击该按钮时将使用MainWindow.xaml.cs中定义的OpenCustomerInformationEntry方法,该方法又将成为CustomerInformationEntry窗口的实例并显示它。

If you would still rather stick with the Forms approach, you can do that by using WindowsFormsHost , usage of which is discussed here . 如果您仍然愿意使用Forms方法,则可以使用WindowsFormsHost来实现此处讨论其用法。

Best Regards, JC 最好的问候,JC

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM