2009-10-30 1 views
6

WinForm 이벤트 처리에 유창한 접근 방식이 있습니까?

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

과 같은 이벤트를 처리하기위한 유창한 코드를 입력하기위한 라이브러리가 있는지 궁금했을 때 사용자 컨트롤에서 다른 KeyDown 이벤트를 처리하고있었습니다. 존재합니까?

+0

멋진 아이디어! 나는 Jeremy Miller가 StoryTeller (http://storyteller.tigris.org/source/browse/storyteller/trunk/)에 대해 약간의 연구를 해왔을 것 같은 이런 것을 보지 못했습니까? –

답변

5

나는 이것이 도전이었고, 이것이 내가 플루 언트가 무엇인지 배울 수 있다고 결정했다. 그래서 나는 플루트 키보드 클래스를 코딩했다. 나는 모든 유창한 언어 구조와 규칙을 따르지 않는다고 생각하지만, 제대로 작동합니다.

도우미 확장 방법

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

유창 클래스

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

지금

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

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

입력 할 수 있습니다 Ctrl 키 + F가 다운 때 메시지 박스에만 표시됩니다.

2

.NET 4는 정확하게 제공해야하는 반응 프레임 워크 (IObservable<T>, IObserver<T> 및 도우미 확장 유형)를 소개합니다.

+0

반응 프레임 워크는 이에 대한 유창한 인터페이스를 제공하지 않습니다. 상당히 다른 이벤트에 LINQ를 제공합니다. –

+0

오늘 Rx 프레임 워크에 대한 기사가 나타났습니다. .NET Framework 3.5 sp1에서 사용할 수 있습니다. 나는 똑같은 일을 시도했지만 훨씬 더 많은 옵션으로 완벽하게 작동했습니다. –

3

.Net Framework 3.5 SP1 용으로 Reactive Extension Framework을 다운로드했습니다.

나는 동일한 기능을 수행 할 수 있었다 : 이것은 꽤 강력한 물건

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

입니다.