2009-10-30 12 views
6

mi stava gestendo un altro evento KeyDown in un controllo utente quando mi sono chiesto se esistesse una libreria per la digitazione del codice fluente per la gestione degli eventi comeEsiste un approccio fluido alla gestione dell'evento WinForm?

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

fa che esistono?

+0

Fantastica idea! Non ho visto nulla di simile, forse Jeremy Miller ha lavorato su StoryTeller (http://storyteller.tigris.org/source/browse/storyteller/trunk/)? –

risposta

5

Ho deciso che questa era una sfida e che questo mi avrebbe permesso di imparare cos'è Fluent, quindi ho codificato una classe di tastiera Fluent. Non penso di seguire tutte le regole e le regole linguistiche fluenti, ma funziona.

metodo di estensione Helper

/// <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 classe fluente

/// <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; 
    } 
} 

ora posso digitare

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

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

e visualizzerà solo la messagebox quando Ctrl + F è giù.

2

.NET 4 introdurrà il framework reattivo (IObservable<T>, IObserver<T> e i tipi di estensione helper) che dovrebbe offrire esattamente questo.

+0

Il framework reattivo non fornisce un'interfaccia fluida per questo. Fornisce LINQ agli eventi, che è abbastanza diverso. –

+0

Oggi sono incappato in un articolo su Rx Framework ed è disponibile su .NET Framework 3.5 sp1. Ho provato a fare la stessa cosa e ha funzionato perfettamente con molte più opzioni. –

3

Ho scaricato il Reactive Extension Framework per .Net Framework 3.5 SP1.

sono stato in grado di fare lo stesso:

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())); 

Questa è roba abbastanza potente.

Problemi correlati