.NET快速开发实践之应用IExtenderProvider实现控件焦点跳转

         我在前面的.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群:15118502

链接:AgileEAS.NET应用开发平台介绍

AgileEAS.NET之敏捷并行开发方法

敏捷软件工程实验室

时间: 2024-09-24 07:27:43

.NET快速开发实践之应用IExtenderProvider实现控件焦点跳转的相关文章

.NET快速开发实践之应用IExtenderProvider实现输入法自动切换

         我在前面的.NET快速开发实践中的IExtenderProvider扩展组件和.NET快速开发实践之应用IExtenderProvider实现对象与UI控件的绑定两篇Post介绍了IExtenderProvider扩展编程模式和应用IExtenderProvider实现实体与对象的做法与例子,下面我为介绍一下在管理信息系统开发中一个常用的功能,输入法的切换,很多在线事务处理系统业务量非常的繁忙,在特定的某个时刻,比如在his应用中的挂号.收费,窗口业务中业务办理者排着长长的队,

.NET快速开发实践之应用IExtenderProvider实现对象与UI控件的绑定

         现在企业级的信息系统应用开发之中,数据层采用了ORM,解放了之前开发最大工作量的核对SQL语句,我到现在还曾经记得在2002年实医院管理信息系统时对齐一个插入数据的SQL语言搞的我头大,从那之后就能不能把这样的东西换个方式,之后搞.NET有了ORM,对齐SQL语句的事终于解放了,但是界面上的UI与ORM对象之间的数据交互避免不了,把数据实体的值显示在UI控件上或者把UI控件的值更新到数据对象,我们不得不这样去写:          取实体的值并显示在界面: private vo

.NET快速开发实践中的IExtenderProvider扩展组件

          说起扩展编程组件,我们不得不起到一个接口IExtenderProvider,参考msdn的定义:定义将属性扩展到容器中的其他组件的接口;下面我贴上IExtenderProvider的定义: /// <summary> /// 定义将属性扩展到容器中的其他组件的接口. /// </summary> public interface IExtenderProvider { /// <summary> /// 指定此对象是否可以将其扩展程序属性提供给指定的

使用NSun快速开发项目之NSun.NPage(分页控件)

在Winform开发中分页控件是必不可少的.而在Web开发中AspNetPage 能够使 得分页显示变的非常容易便捷. 基于bindingNavigator控件的基础上进行二次开发,使得在Winform开发中分 页显示变的更加方便. NPage: Npage使用方法: 将dll拖入工具箱,显示如下 控件拖入窗体显示如下:

ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性

原文:ASP.NET2.0自定义控件组件开发 第六章 深入讲解控件的属性                                         深入讲解控件的属性持久化(一) 系列文章链接: ASP.NET自定义控件组件开发 第一章 待续 ASP.NET自定义控件组件开发 第一章 第二篇 接着待续 ASP.NET自定义控件组件开发 第一章 第三篇 ASP.NET自定义控件组件开发 第二章 继承WebControl的自定义控件 ASP.NET自定义控件组件开发 第三章 为控件添加事件 前

开发ASP.NET Atlas服务器端Extender控件—编写服务器端Extender &amp; Dflying近期动向

asp.net|服务器|控件 PS:承蒙各位厚爱,在博客园中安家的两个月中我学到了不少东西,认识了许多朋友,且得到了好多机会.目前我有幸翻译一本Atlas的书:Foundations of Atlas: Rapid Ajax Development with ASP.NET 2.0,估计三个月后即可于人民邮电出版社并面世.所以这段时间比较忙,Blog也不能有前一段时间那么频繁的更新了,特此表示歉意.当然,欢迎朋友们继续来讨论Atlas的相关问题,我会尽力回答. 未来的两个月内,对于Foundat

Android开发入门(十一)选择控件 11.2 DatePicker

DataPicker和上一节讲的TimePicker很相似.使用DatePicker,可以让用户选择一个特定的日期.下面展 示如何使用DatePicker. 1. 使用上一节的工程,BasicViews4,修改main.xml. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/and

Android开发入门(十一)选择控件 11.1 TimePicker

使用TimePicker,可以让用户去选择一天中的事件,包括24小时制和AM/PM制.下面的例子将会展示如何 使用TimePicker. 1. 创建一个工程:BasicViews4. 2. main.xml中的代码. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android&q

Android开发入门(十)基本控件 10.4 AutoCompleteTextView

AutoCompleteTextView和EditText很相似,事实上,AutoCompleteTextView就是EditText的子类.使用 AutoCompleteTextView,当用户正在输入时,会自动弹出一些提示信息.下面的例子将会展示如何使用 AutoCompleteTextView去自动地帮助用户完成输入. 1. 创建一个工程:BasicViews3. 2. main.xml中的代码. <?xml version="1.0" encoding="utf