Enter jako tabulátor

Podnět k napsání tohoto příspěvku přišel z dotazu do konference o .NET VSNET-L. A to konkrétně WinForms: poradi controlu a jak se stiskem Enter presunout na další textbox :-). A to hlavně první část otázky.

Když jsem si přečetl odpovědi, obzvláště tu, ve které se radí podědit použité prvky vzpoměl jsem si na své začátky v OOP. Ano, takhle se to dá také řešit. Teda pokud chcete pro každou novou věc dědit ze současného stavu prvků a psát kód několikrát. Brrr. Dovedu si představit takový chytrý prvek, který bude úžasný a dokáže splnit všechno co si programátor dokáže jen přát. Co s ním však v další aplikaci? Co s jeho údržbou a dalším rozvojem? Co když se mi bude líbit nějaký jiný povedený prvek a já k němu budu chtít doplnit všechny mé úžasné vychytávky? Skutečně je budu muset přepisovat a vytvářet další úroveň ve třídní hierarchii?

Použijeme IExtenderProvider

Dost už černých myšlenek. Na takovéhle vychytávky je tu přeci IExtenderProvider. Jestliže chceme rozšířit funkčnost prvků, můžeme použít toto jednoduché rozhraní. Asi nemá význam se teď rozepisovat o tom, jak jej implementovat, je to skutečně jednoduché a spoustu příkladů je možné nalézt třeba na CodeProject.

EnterAsTabProvider

K vyřešení tazatelovi otázky je tak možné přistoupit ještě jinak. A proto jsem napsal velice jednoduchý provider, který zajistí posun na následující prvek v okamžiku stisku klávesy Enter. Nazval jsem jej jednoduše EnterAsTabProvider. Na co je ovšem důležité myslet! Na obrazovce jsou umístěny takové prvky, kterým by funkčnost stisku klávesy Enter neměla být upřena. Dokonce je vyžadováno, aby tuto funkci podporovali a uživatel z nich po stisku klávesy neodskočil. Narychlo mě napadá třeba stisk tlačítka. A tak jsem zpřístupnil vlastnost pro možnost aktivace/deaktivace chování (posunu) po stisku klávesy Enter.

Vlastní kód

	[ProvideProperty("Enabled", typeof(Control))]
	public class EnterAsTabProvider: Component, IExtenderProvider  {

		/// 
		/// Store properties for extendee control
		/// 
		private Hashtable properties;

		#region Public contructor
		public EnterAsTabProvider() {
			properties = new Hashtable();
		}

		public EnterAsTabProvider(IContainer container): this() {
			container.Add(this);
		}
		#endregion 

		#region IExtenderProvider Members

		/// 
		/// Can extend Controls w/o Form and ToolBar
		/// 
		/// 
		/// Gets info about can extend object
		public bool CanExtend(object extendee) {
			if ((extendee is Control) && !(extendee is Form)) {
				return !(extendee is ToolBar);
			}
			return false;
		}

		#endregion

		/// 
		/// Is move enabled for this Control
		/// 
		/// attached Control
		/// Gets info if provider is enabled or disabled
		public bool GetEnabled(Control control) {
			return GetControlProperties(control).Enabled;
		}

		/// 
		/// Sets info if provider will be enabled or disabled
		/// 
		/// Control
		/// set enabled or disabled provider
		public void SetEnabled(Control control, bool enabled) {
			GetControlProperties(control).Enabled = enabled;
		}


		/// 
		/// Provide properties for Control
		/// 
		/// Control
		/// gets EnterAsTabExtendedProperties
		private EnterAsTabExtendedProperties GetControlProperties(Control control) {
			if (properties.Contains(control)) {
				return properties[control] as EnterAsTabExtendedProperties;
			} else {
				EnterAsTabExtendedProperties prop = new EnterAsTabExtendedProperties();
				properties.Add(control, prop);
				control.KeyDown += new KeyEventHandler(KeyDownHandler);
				return prop;
			}
		}

		/// 
		/// This is the main method for this provider. It provides functionality for changing enter to tab.
		/// 
		/// sender, Control on which was the key pressed
		/// KeyEventArgs information
		private void KeyDownHandler(object sender, KeyEventArgs e) {
			Control control = sender as Control;
			if ((e.KeyCode == Keys.Enter) && (control != null)) {
				if (GetControlProperties(control).Enabled)
					if (control.FindForm().SelectNextControl(control, true, false, true, true))
						e.Handled = true;
			}
		}

		/// 
		/// private class to store information 
		/// 
		private class EnterAsTabExtendedProperties {
			public bool Enabled = true; 
		}

Tento kód stačí umístit do samostatné assembly a zpřístupnit si tento prvek na Toolbaru. Přetažením tohoto prvku na formulář se nám ukáže u každého prvku, poděděného od Control (mimo Form a ToolBar) další vlastnost, nejspíše pojmenovaná jako Enabled on ....

Meze dalšímu rozvoji se nekladou a budu jen rád, pokud mi tady dáte vědět, jak jste jej rozšířili vy.

Věřím, že tento způsob rozšiřování funkčnosti se vám bude zamlouvat více, než na začátku zmiňované dědění. Příjemnou zábavu a hezký den.

1 Comment

Add a Comment