我在前面的.NET快速开发实践中的IExtenderProvider扩展组件和其他两篇Post介绍了IExtenderProvider扩展编程模式和应用IExtenderProvider实现实体与对象的做法与例子,下面我为介绍一下在管理信息系统开发中一个常用的功能,控件的输入焦点跳转,我们知道,系统为我们提供了Tab和Shift+Tab切换输入焦点的功能,但是这里面有一个问题,即最终操作者最不习惯于使用Tab进行切换输入焦点,因为都已经习惯于无鼠标操作,常使用回车,上下方向键进行操作以实现焦点切换。
那么我们如何实现这样的功能,最普通的方法是处理输入控件的KeyDown事件,判读按键是否满足跳转:例如
private void tbName_KeyDown(object sender, KeyEventArgs e) { if(e.KeyCode == Keys.Enter) //回车向下一焦点跳转 { this.tbInputCode1.Focus(); } else if(e.KeyCode == Keys.Up) //向上键向上一焦点跳转 { this.tbCode.Focus(); }
这样的做法,我们就必须重写所有输入控件的KeyDown事件,效率低下,也影响代码的美观,我们可以通过应用应用IExtenderProvider实现另一种方式,即把这样的功能封装在一个名字叫ControlFocus的组件中:
[ToolboxItem(true)] [Description("控制焦点跳转组件")] [ProvideProperty( "NextControl", typeof(Control)) ] [ProvideProperty("PreviousControl", typeof(Control))] public class ControlFocus:Component, IExtenderProvider { Dictionary<Control, Control> _NextFocus = new Dictionary<Control, Control>(); Dictionary<Control, Control> _PreviousFocus = new Dictionary<Control, Control>(); private Keys [] nextKeys; private Keys[] previousKeys; public ControlFocus() { } public ControlFocus(System.ComponentModel.IContainer container) { container.Add(this); } [Category("焦点跳转")] [Description("获取/设置向前跳转按键集合")] public Keys[] NextKeys { get { return this.nextKeys; } set { this.nextKeys = value; } } [Category("焦点跳转")] [Description("获取/设置向后跳转按键集合")] public Keys[] PreviousKeys { get { return this.previousKeys; } set { this.previousKeys = value; } } [Category("焦点跳转")] [Description("获取/设置向前跳转控件")] public System.Windows.Forms.Control GetNextControl(Control control) { if (_NextFocus.ContainsKey(control)) { return _NextFocus[control]; } return null; } public void SetNextControl(Control control, Control nextControl) { if (_NextFocus.ContainsKey(control) != true) { _NextFocus.Add(control,nextControl); control.KeyDown += new KeyEventHandler(Control_KeyDown); } else { _NextFocus[control] = nextControl; } } [Category("焦点跳转")] [Description("获取/设置向后跳转控件")] public Control GetPreviousControl(Control control) { if (_PreviousFocus.ContainsKey(control)) { return (System.Windows.Forms.Control)_PreviousFocus[control]; } return null; } public void SetPreviousControl(Control control, Control previousControl) { if (_PreviousFocus.ContainsKey(control) != true) { _PreviousFocus.Add(control,previousControl); control.KeyDown += new KeyEventHandler(Control_KeyDown); } else { _PreviousFocus[control] = previousControl; } } private void Control_KeyDown(object sender, KeyEventArgs e) { if(NextKeysContains(e.KeyCode)) { Control nextControl = this.GetNextControl((Control)sender); if(nextControl != null && nextControl.CanFocus) nextControl.Focus(); } else if (PreviousKeysContains(e.KeyCode)) { Control previousControl = this.GetPreviousControl((Control)sender); if(previousControl != null && previousControl.CanFocus) previousControl.Focus(); } } internal bool NextKeysContains(Keys k) { if (this.nextKeys == null) return false; for (int i = 0; i < this.nextKeys.Length; i++) { if (this.nextKeys[i] == k) return true; } return false; } internal bool PreviousKeysContains(Keys k) { if (this.previousKeys == null) return false; for (int i = 0; i < this.previousKeys.Length; i++) { if (this.previousKeys[i] == k) return true; } return false; } #region IExtenderProvider 成员 bool IExtenderProvider.CanExtend(object component) { if (component is Control && !(component is Form)) { return true; } return false; } #endregion }
下面我们来看看如何应用ControlFocus,拖出一个ControlFocus设置跳转按键值,可以通过属性窗口,也可以通过代码:
public DiagnosisEditor() { InitializeComponent(); this.controlFocus1.NextKeys = new Keys[] {Keys.Enter,Keys.PageDown}; this.controlFocus1.PreviousKeys = new Keys [] {Keys.PageUp}; }
下面设置输入控件的焦点跳转顺序,需要为每个控件设置下一个焦点控件和前一焦点控件:
我做了一个简单的demo,请下载Exam.DataUIMapper.rar。
QQ群:120661978,125643764
本文转自 agilelab 51CTO博客,原文链接:http://blog.51cto.com/agilelab/561931