业务系统中,很多录入人员习惯于用Enter键来代替Tab键切换控件焦点(虽然我个人并不觉得这样录入速度会变得有多高效,呵呵),有需求了,自然就得想办法满足。
思路:为了更灵活的控件焦点顺序,我决定用TabIndex来做文章,每个输入控件按下回车时,找到下一个比当前控件TabIndex更大且最接近的控件,然后focus().
XAML界面部分:
代码语言:javascript复制<UserControl x:Class="tab_key_test.MainPage"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBox Margin="5" TabIndex="0"></TextBox>
<CheckBox Margin="5" TabIndex="1" Content="CheckBox Test"></CheckBox>
<TextBox Margin="5" TabIndex="2"></TextBox>
<ComboBox Margin="5" TabIndex="3">
<ComboBox.Items>
<ComboBoxItem Content="ComboBox Test 11"></ComboBoxItem>
<ComboBoxItem Content="ComboBox Test 22"></ComboBoxItem>
</ComboBox.Items>
</ComboBox>
<TextBox Margin="5" TabIndex="4"></TextBox>
<RadioButton Margin="5" Content="Radio Test" TabIndex="5"></RadioButton>
<TextBox Margin="5" TabIndex="6"></TextBox>
</StackPanel>
</UserControl>
CS后端代码:
代码语言:javascript复制using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace tab_key_test
{
public partial class MainPage : UserControl
{
List<Control> allInputControls = new List<Control>();
public MainPage()
{
InitializeComponent();
this.Loaded = MainPage_Loaded;
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
//把界面上的TextBox,RadioButton,ComboBox,CheckBox都加入列表
//注:一般业务录入界面上只有这4种类型的输入控件,如果还有其实类型,可自行扩展
allInputControls.AddRange(FindChildren<TextBox>(LayoutRoot).Cast<Control>());
allInputControls.AddRange(FindChildren<RadioButton>(LayoutRoot).Cast<Control>());
allInputControls.AddRange(FindChildren<ComboBox>(LayoutRoot).Cast<Control>());
allInputControls.AddRange(FindChildren<CheckBox>(LayoutRoot).Cast<Control>());
//按TabIndex排序
allInputControls = allInputControls.OrderBy(c => c.TabIndex).ToList();
foreach (Control c in allInputControls)
{
c.KeyDown = EnterKeyDownToTab;
if (c is ComboBox)
{
//ComboBox要特殊处理
(c as ComboBox).DropDownClosed = DropDownClosedToNext;
}
}
}
void EnterKeyDownToTab(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
GoToNextControl(sender);
}
}
void GoToNextControl(object sender)
{
var self = sender as Control;
if (self == null)
{
return;
}
var selfTabIndex = self.TabIndex;
//找出下一个控件
var nextControl = allInputControls.FirstOrDefault(c => c.TabIndex > selfTabIndex);
if (nextControl != null)
{
nextControl.Focus();
}
else
{
allInputControls[0].Focus();//最后一个控件时,再跳到第一个(可选处理)
}
}
/// <summary>
/// 查找所有子元素(递归)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="parent"></param>
/// <returns></returns>
public static IEnumerable<T> FindChildren<T>(DependencyObject parent) where T : class
{
int count = VisualTreeHelper.GetChildrenCount(parent);
if (count > 0)
{
for (int i = 0; i < count; i )
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
var t = child as T;
if (t != null)
yield return t;
IEnumerable<T> children = FindChildren<T>(child);
foreach (T item in children)
yield return item;
}
}
}
private void DropDownClosedToNext(object sender, EventArgs e)
{
GoToNextControl(sender);
}
}
}
这个思路还可以应用到html网页上:
代码语言:javascript复制<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Enter Key Replace Tab</title>
<script type="text/javascript" src="http://lib.sinaapp.com/js/jquery/1.6/jquery.min.js"></script>
<style type="text/css">
input,select,textarea{
padding:0;
margin:5px;
width:150px;
display:block;
}
</style>
<script type="text/javascript">
$(document).ready(function(){
var inputs = $("input,textarea,select").sort(function(a,b){return a.tabIndex>b.tabIndex?1:-1});
inputs.each(function(){
$(this).keypress(function(e){
if (e.keyCode==13||e.which==13){
//修正textarea的多余回车问题(可选)
//if ($(this).get(0).tagName == "TEXTAREA"){
// $(this).val($.trim($(this).val()));
//};
var selfTabIndex = parseInt($(this).attr("tabIndex"),10);
var nextInput = null;
//找出下一个元素
for(var i=0; i<inputs.length; i ){
if (inputs[i].tabIndex > selfTabIndex){
nextInput = inputs[i];
break;
}
}
if (nextInput != null){
nextInput.focus();
}
else{
inputs[0].focus();
}
}
}).focus(function(){
$(this).select();
})
})
})
</script>
</head>
<body>
<input type="text" tabindex="0" value="000"/>
<input type="text" tabindex="1" value="111"/>
<textarea tabindex="2">222</textarea>
<input type="radio" tabindex="3" id="r3" style="width:20px;display:inline"/><label for="r3">333</label>
<input type="text" tabindex="4" value="444"/>
<input type="checkbox" tabindex="5" id="c5" style="width:20px;display:inline"/><label for="c5">555</label>
<input type="text" tabindex="6" value="666"/>
<select tabindex="7">
<option>777</option>
<option>xxx</option>
</select>
<select size="2" tabindex="8">
<option>888</option>
<option>yyy</option>
</select>
</body>
</html>