Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Test/UnitTests/EventTriggerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public class EventTriggerTest

[TestInitialize]
public void Setup()
{
Interaction.ShouldRunInDesignMode = true;
}
{
Interaction.ShouldRunInDesignMode = true;
}

[TestCleanup]
public void Teardown()
Expand Down
181 changes: 181 additions & 0 deletions Test/UnitTests/KeyTriggerTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xaml.Behaviors;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows;
using Microsoft.Xaml.Behaviors.Input;
using System.Windows.Interop;
using System;

namespace Microsoft.Xaml.Interactions.UnitTests
{
[TestClass]
public class KeyTriggerTest
{
#region Setup/teardown

[TestInitialize]
public void Setup()
{
Interaction.ShouldRunInDesignMode = true;
}

[TestCleanup]
public void Teardown()
{
Interaction.ShouldRunInDesignMode = false;
}

#endregion

#region Test methods

[TestMethod]
[DataRow(Key.A)]
[DataRow(Key.B)]
[DataRow(Key.C)]
[DataRow(Key.D)]
[DataRow(Key.E)]
[DataRow(Key.F)]
[DataRow(Key.G)]
[DataRow(Key.H)]
[DataRow(Key.I)]
[DataRow(Key.J)]
[DataRow(Key.K)]
[DataRow(Key.L)]
[DataRow(Key.M)]
[DataRow(Key.N)]
[DataRow(Key.O)]
[DataRow(Key.P)]
[DataRow(Key.Q)]
[DataRow(Key.R)]
[DataRow(Key.S)]
[DataRow(Key.T)]
[DataRow(Key.U)]
[DataRow(Key.V)]
[DataRow(Key.W)]
[DataRow(Key.X)]
[DataRow(Key.Y)]
[DataRow(Key.Z)]
[DataRow(Key.NumPad1)]
[DataRow(Key.NumPad2)]
[DataRow(Key.NumPad3)]
[DataRow(Key.NumPad4)]
[DataRow(Key.NumPad5)]
[DataRow(Key.NumPad6)]
[DataRow(Key.NumPad7)]
[DataRow(Key.NumPad8)]
[DataRow(Key.NumPad9)]
[DataRow(Key.Enter)]
[DataRow(Key.Tab)]
public void KeyTrigger_InvokesActions_WhenKeyIsPressed(Key key)
{
var textBox = new TextBox();
var keyTrigger = new KeyTrigger { Key = key };
var action = new StubAction();
keyTrigger.Actions.Add(action);
keyTrigger.Attach(textBox);

Grid grid = new Grid();
grid.Children.Add(textBox);
using (StubWindow window = new StubWindow(grid))
{
var inputSource = PresentationSource.FromVisual(textBox) ?? new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero);
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, inputSource, 0, key);
keyEventArgs.RoutedEvent = Keyboard.KeyDownEvent;
textBox.RaiseEvent(keyEventArgs);

Assert.AreEqual(1, action.InvokeCount);
}
}

[TestMethod]
[DataRow(Key.A)]
[DataRow(Key.B)]
[DataRow(Key.C)]
[DataRow(Key.D)]
[DataRow(Key.E)]
[DataRow(Key.F)]
[DataRow(Key.G)]
[DataRow(Key.H)]
[DataRow(Key.I)]
[DataRow(Key.J)]
[DataRow(Key.K)]
[DataRow(Key.L)]
[DataRow(Key.M)]
[DataRow(Key.N)]
[DataRow(Key.O)]
[DataRow(Key.P)]
[DataRow(Key.Q)]
[DataRow(Key.R)]
[DataRow(Key.S)]
[DataRow(Key.T)]
[DataRow(Key.U)]
[DataRow(Key.V)]
[DataRow(Key.W)]
[DataRow(Key.X)]
[DataRow(Key.Y)]
[DataRow(Key.Z)]
[DataRow(Key.NumPad1)]
[DataRow(Key.NumPad2)]
[DataRow(Key.NumPad3)]
[DataRow(Key.NumPad4)]
[DataRow(Key.NumPad5)]
[DataRow(Key.NumPad6)]
[DataRow(Key.NumPad7)]
[DataRow(Key.NumPad8)]
[DataRow(Key.NumPad9)]
[DataRow(Key.Enter)]
[DataRow(Key.Tab)]
public void KeyTrigger_InvokesActions_WhenKeyIsReleased(Key key)
{
var textBox = new TextBox();
var keyTrigger = new KeyTrigger { Key = key, FiredOn = KeyTriggerFiredOn.KeyUp };
var action = new StubAction();
keyTrigger.Actions.Add(action);
keyTrigger.Attach(textBox);

Grid grid = new Grid();
grid.Children.Add(textBox);
using (StubWindow window = new StubWindow(grid))
{
var inputSource = PresentationSource.FromVisual(textBox) ?? new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero);
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, inputSource, 0, key);
keyEventArgs.RoutedEvent = Keyboard.KeyUpEvent;
textBox.RaiseEvent(keyEventArgs);

Assert.AreEqual(1, action.InvokeCount);
}
}


[TestMethod]
[DataRow(true)]
[DataRow(false)]
public void KeyTrigger_InvokesActionsOnce_WhenLoadedEventFiredMultipleTimes(bool activeOnFocus)
{
var textBox = new TextBox();
var keyTrigger = new KeyTrigger { ActiveOnFocus = activeOnFocus, Key = Key.Enter };
var action = new StubAction();
keyTrigger.Actions.Add(action);
keyTrigger.Attach(textBox);

Grid grid = new Grid();
grid.Children.Add(textBox);
using (StubWindow window = new StubWindow(grid))
{
//simulate the loaded event being invoked multiple times; for example, when using an element in a tab control
textBox.RaiseEvent(new RoutedEventArgs(FrameworkElement.LoadedEvent));

var inputSource = PresentationSource.FromVisual(textBox) ?? new HwndSource(0, 0, 0, 0, 0, "", IntPtr.Zero);
var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, inputSource, 0, Key.Enter);
keyEventArgs.RoutedEvent = Keyboard.KeyDownEvent;
textBox.RaiseEvent(keyEventArgs);

Assert.AreEqual(1, action.InvokeCount);
}
}

#endregion
}
}
6 changes: 5 additions & 1 deletion src/Microsoft.Xaml.Behaviors/EventTriggerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,11 @@ private void RegisterLoaded(FrameworkElement associatedElement)
}
}

private void UnregisterLoaded(FrameworkElement associatedElement)
/// <summary>
/// Removes the event handler from the Loaded event of the associated object.
/// </summary>
/// <param name="associatedElement">The associated object</param>
protected void UnregisterLoaded(FrameworkElement associatedElement)
{
Debug.Assert(this.eventHandlerMethodInfo == null);
if (this.IsLoadedRegistered && associatedElement != null)
Expand Down
4 changes: 4 additions & 0 deletions src/Microsoft.Xaml.Behaviors/Input/KeyTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ protected override void OnEvent(EventArgs eventArgs)
{
this.targetElement.KeyUp += this.OnKeyPress;
}

// Unregister the Loaded event of the Source object to prevent the KeyUp or KeyDown events from being registered multiple times.
// this is especially important when the KeyTrigger is used in a TabControl/TabItem.
UnregisterLoaded(Source as FrameworkElement);
}

protected override void OnDetaching()
Expand Down