2009-10-30 17 views
6

estaba manejando otro evento KeyDown de un control de usuario que me preguntaba si existía una biblioteca para escribir código de fluidez para el manejo de eventos como¿Existe un enfoque fluido para manejar el evento WinForm?

editor.When(Keys.F).IsDown().With(Keys.Control).Do((sender, e) => ShowFindWindow()); 

¿Eso existe?

+0

¡Idea genial! No he visto nada como esto, tal vez Jeremy Miller ha hecho algún trabajo en StoryTeller (http://storyteller.tigris.org/source/browse/storyteller/trunk/)? –

Respuesta

5

Decidí que esto era un desafío y que esto podría permitirme aprender qué es Fluent, así que codifiqué una clase de teclado Fluido. No creo que siga toda la estructura y las reglas del lenguaje con fluidez, pero funciona.

método de extensión ayudante

/// <summary> 
/// Provides a set of static (Shared in Visual Basic) methods for starting a fluent expression on a <see cref="System.Windows.Form.Control"/> object. 
/// </summary> 
public static class ControlExtensions 
{ 
    /// <summary> 
    /// Starts a fluent expression that occurs when a key is pressed. 
    /// </summary> 
    /// <param name="control">The control on which the fluent keyboard expression is occuring.</param> 
    /// <param name="keys">The key when it will happen.</param> 
    /// <returns>A <see cref="KeyboardFluent"/> object that makes it possible to write a fluent expression.</returns> 
    public static KeyboardFluent When(this Control control, Keys keys) 
    { 
     return new KeyboardFluent(control).When(keys); 
    } 
} 

La clase fluidez

/// <summary> 
/// Represents a fluent expression for handling keyboard event. 
/// </summary> 
public class KeyboardFluent 
{ 
    /// <summary> 
    /// The control on which the fluent keyboard expression is occuring. 
    /// </summary> 
    private Control control; 

    /// <summary> 
    /// The KeyDown and KeyUp handler. 
    /// </summary> 
    private KeyEventHandler keyHandler; 

    /// <summary> 
    /// Stores if the IsDown method was called and that the KeyDown event is registered. 
    /// </summary> 
    private bool isDownRegistered = false; 

    /// <summary> 
    /// Stores if the IsUp method was called and that the KeyUp event is registered. 
    /// </summary> 
    private bool isUpRegistered = false; 

    /// <summary> 
    /// The list of keys that will make the actions be executed when they are down or up. 
    /// </summary> 
    private List<Keys> triggerKeys; 

    /// <summary> 
    /// The modifiers keys that must be down at the same time than the trigger keys for the actions to be executed. 
    /// </summary> 
    private Keys modifiers; 

    /// <summary> 
    /// The list of actions that will be executed when the trigger keys and modifiers are down or up. 
    /// </summary> 
    private List<Action<object, KeyEventArgs>> actions; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="KeyboardFluent"/> class. 
    /// </summary> 
    /// <param name="control">The control on which the fluent keyboard expression is occuring.</param> 
    public KeyboardFluent(Control control) 
    { 
     this.control = control; 
     this.triggerKeys = new List<Keys>(); 
     this.actions = new List<Action<object, KeyEventArgs>>(); 
     this.keyHandler = new KeyEventHandler(OnKeyHandler); 
    } 

    /// <summary> 
    /// Handles the KeyDown or KeyUp event on the control. 
    /// </summary> 
    /// <param name="sender">The control on which the event is occuring.</param> 
    /// <param name="e">A <see cref="KeyEventArgs"/> that gives information about the keyboard event.</param> 
    private void OnKeyHandler(object sender, KeyEventArgs e) 
    { 
     if (this.triggerKeys.Contains(e.KeyCode) && e.Modifiers == this.modifiers) 
     { 
      this.actions.ForEach(action => action(sender, e)); 
     } 
    } 

    /// <summary> 
    /// Makes the keyboard event occured when a key is pressed down. 
    /// </summary> 
    /// <returns>Returns itself to allow a fluent expression structure.</returns> 
    public KeyboardFluent IsDown() 
    { 
     if (!isDownRegistered) 
     { 
      this.control.KeyDown += this.keyHandler; 
      isDownRegistered = true; 
     } 
     return this; 
    } 

    /// <summary> 
    /// Makes the keyboard event occured when a key is pressed up. 
    /// </summary> 
    /// <returns>Returns itself to allow a fluent expression structure.</returns> 
    public KeyboardFluent IsUp() 
    { 
     if (!isUpRegistered) 
     { 
      this.control.KeyUp += this.keyHandler; 
      isUpRegistered = true; 
     } 
     return this; 
    } 

    /// <summary> 
    /// Creates a new trigger on a key. 
    /// </summary> 
    /// <param name="key">The key on which the actions will occur.</param> 
    /// <returns>Returns itself to allow a fluent expression structure.</returns> 
    public KeyboardFluent When(Keys key) 
    { 
     this.triggerKeys.Add(key); 
     return this; 
    } 

    /// <summary> 
    /// Adds a modifier filter that is checked before the action are executed. 
    /// </summary> 
    /// <param name="modifiers">The modifier key.</param> 
    /// <returns>Returns itself to allow a fluent expression structure.</returns> 
    public KeyboardFluent With(Keys modifiers) 
    { 
     this.modifiers |= modifiers; 
     return this; 
    } 

    /// <summary> 
    /// Executes the action when the specified keys and modified are either pressed down or up. 
    /// </summary> 
    /// <param name="action">The action to be executed.</param> 
    /// <returns>Returns itself to allow a fluent expression structure.</returns> 
    public KeyboardFluent Do(Action<object, KeyEventArgs> action) 
    { 
     this.actions.Add(action); 
     return this; 
    } 
} 

ahora puedo escriba

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     this.When(Keys.F).With(Keys.Control).IsDown().Do((sender, e) => MessageBox.Show(e.KeyData.ToString())); 
    } 
} 

y se mostrará sólo el cuadro de mensaje cuando Ctrl + F es hacia abajo.

2

.NET 4 introducirá el marco reactivo (IObservable<T>, IObserver<T> y tipos de extensión auxiliar) que debería ofrecer exactamente esto.

+0

El marco reactivo no proporciona una interfaz fluida para esto. Proporciona LINQ a eventos, que es bastante diferente. –

+0

Hoy, me encontré con un artículo sobre el Rx Framework y está disponible en .NET Framework 3.5 sp1. Traté de hacer lo mismo y funcionó perfectamente con muchas más opciones. –

3

He descargado el Reactive Extension Framework para .Net Framework 3.5 SP1.

que era capaz de hacer lo mismo:

Observable.FromEvent<KeyEventArgs>(this, "KeyDown") 
    .Where(e => e.EventArgs.KeyCode == Keys.F && e.EventArgs.Modifiers == Keys.Control) 
    .Subscribe(e => MessageBox.Show(e.EventArgs.KeyData.ToString())); 

Esto es algunas cosas bastante potente.

Cuestiones relacionadas