I’m using the InputManager to check if changes to controls are done by user or code. This works fine, except when user uses the context menu for cut/copy/paste. If the user do ctrl+v in a textbox, InputManager correctly notices it. However, if the paste is done from the context menu of the textbox, the InputManager never fires the PreNotifyInput or PostNotifyInput events. Anyone knows why? Or how to detect that these user actions? Below is a working sample. The lower textblock never gets updated when user uses the cut/copy/paste menu in the above textbox since PreNotifyInput never fires.
XAML:
<Window x:Class="InputMgrDemo.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="300">
<StackPanel>
<TextBox TextChanged="TextBox_TextChanged" />
<TextBlock Name="_text" />
</StackPanel>
</Window>
Code behind:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace InputMgrDemo
{
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
InputManager.Current.PreNotifyInput += ((sender, e) => _userInput = true);
InputManager.Current.PostNotifyInput += ((sender, args) => _userInput = false);
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (_userInput)
{
_text.Text = (sender as TextBox).Text;
}
}
private bool _userInput;
}
}
Actually the PreNotifyInput event does fire on the MouseLeftButtonUp event, but then the PostNotifyInput fires before the actual paste occurs.
Here is the sequence of operations:
Your PostNotifyInput event handler is called since the MouseLeftButtonUp event is handled
Any rendering scheduled by the Dispatcher completes
The Dispatcher invokes the callback in MenuItem
In WPF the effects of “user input” can be arbitrarily delayed by dispatcher callbacks, etc, so you cannot know whether a change is due to user input or not.
In fact, theoretically speaking this is generally true. Consider the following scenarios:
Clearly in each of these cases the change was caused by user input 😉 Do you see where I’m going with this? Philosophically there is no fundamental way to decide whether a change was made by your user or someone else.
If what you really want is “any changes that occur between the time the user clicks the mouse or uses the keyboard in this application and the time the application goes idle,” you can implement this:
But in this case if you have data coming in dynamically from an external feed it may be erroneously considered to be user input.
Another approach is to flip yours upside down: Any time you refresh data from an external data source, set a flag saying you are doing so. Then any time you see changes with that flag not set, you assume it was user interaction. This may be easier to implement if you can ensure that all your external data updates happen above DispatcherPriority.Render.